keycloak-uncached

Changes

distribution/feature-packs/server-feature-pack/src/main/resources/content/standalone/configuration/keycloak-server.json 87(+0 -87)

examples/authz/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml 12(+0 -12)

README.md 1(+1 -0)

server-spi/src/main/java/org/keycloak/storage/changeset/UserData.java 387(+0 -387)

server-spi/src/main/java/org/keycloak/storage/changeset/UserDataAdapter.java 340(+0 -340)

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

testsuite/integration-arquillian/servers/auth-server/jboss/build.xml 42(+0 -42)

testsuite/integration-arquillian/servers/auth-server/jboss/build-truststore.xml 52(+0 -52)

testsuite/integration-arquillian/servers/migration/wildfly_kc12/pom.xml 61(+0 -61)

testsuite/integration-arquillian/servers/migration/wildfly_kc13/pom.xml 62(+0 -62)

testsuite/integration-arquillian/servers/migration/wildfly_kc13/src/main/xslt/datasource.xsl 111(+0 -111)

testsuite/integration-arquillian/servers/migration/wildfly_kc13/src/main/xslt/module.xsl 50(+0 -50)

testsuite/integration-arquillian/servers/migration/wildfly_kc14/assembly.xml 46(+0 -46)

testsuite/integration-arquillian/servers/migration/wildfly_kc14/pom.xml 61(+0 -61)

testsuite/integration-arquillian/servers/migration/wildfly_kc14/src/main/xslt/add-dialect-logger.xsl 45(+0 -45)

testsuite/integration-arquillian/servers/migration/wildfly_kc14/src/main/xslt/datasource.xsl 111(+0 -111)

testsuite/integration-arquillian/servers/migration/wildfly_kc14/src/main/xslt/module.xsl 50(+0 -50)

testsuite/integration-arquillian/servers/migration/wildfly_kc15/assembly.xml 46(+0 -46)

testsuite/integration-arquillian/servers/migration/wildfly_kc15/pom.xml 61(+0 -61)

testsuite/integration-arquillian/servers/migration/wildfly_kc15/src/main/xslt/add-dialect-logger.xsl 45(+0 -45)

testsuite/integration-arquillian/servers/migration/wildfly_kc15/src/main/xslt/datasource.xsl 111(+0 -111)

testsuite/integration-arquillian/servers/migration/wildfly_kc15/src/main/xslt/module.xsl 50(+0 -50)

testsuite/integration-arquillian/servers/migration/wildfly_kc16/assembly.xml 46(+0 -46)

testsuite/integration-arquillian/servers/migration/wildfly_kc16/pom.xml 61(+0 -61)

testsuite/integration-arquillian/servers/migration/wildfly_kc16/src/main/xslt/add-dialect-logger.xsl 45(+0 -45)

testsuite/integration-arquillian/servers/migration/wildfly_kc16/src/main/xslt/datasource.xsl 111(+0 -111)

testsuite/integration-arquillian/servers/migration/wildfly_kc16/src/main/xslt/module.xsl 50(+0 -50)

testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/WEB-INF/photoz-ds.xml 12(+0 -12)

testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SAMLFilterDependency.java 87(+0 -87)

testsuite/integration-arquillian/tests/base/src/test/resources/migration-test/migration-realm-15.json 751(+0 -751)

Details

diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java
index cfe5ff9..bbbf573 100644
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/AbstractPolicyEnforcer.java
@@ -32,6 +32,7 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCon
 import org.keycloak.representations.idm.authorization.Permission;
 
 import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -55,7 +56,7 @@ public abstract class AbstractPolicyEnforcer {
         this.enforcerConfig = policyEnforcer.getEnforcerConfig();
         this.authzClient = policyEnforcer.getClient();
         this.pathMatcher = new PathMatcher();
-        this.paths = policyEnforcer.getPaths();
+        this.paths = new ArrayList<>(policyEnforcer.getPaths());
     }
 
     public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java
index aa6d3d2..88ef9ce 100644
--- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java
+++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/authorization/PolicyEnforcer.java
@@ -33,8 +33,12 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathCon
 import org.keycloak.representations.idm.authorization.Permission;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -95,8 +99,8 @@ public class PolicyEnforcer {
         return authzClient;
     }
 
-    List<PathConfig> getPaths() {
-        return paths;
+    public List<PathConfig> getPaths() {
+        return Collections.unmodifiableList(paths);
     }
 
     KeycloakDeployment getDeployment() {
@@ -154,13 +158,27 @@ public class PolicyEnforcer {
 
                     pathConfig.setId(registrationResponse.getId());
                 } else {
-                    throw new RuntimeException("Could not find matching resource on server with uri [" + path + "] or name [" + resourceName + ". Make sure you have created a resource on the server that matches with the path configuration.");
+                    throw new RuntimeException("Could not find matching resource on server with uri [" + path + "] or name [" + resourceName + "]. Make sure you have created a resource on the server that matches with the path configuration.");
                 }
             } else {
                 pathConfig.setId(search.iterator().next());
             }
 
-            paths.add(pathConfig);
+            PathConfig existingPath = null;
+
+            for (PathConfig current : paths) {
+                if (current.getId().equals(pathConfig.getId()) && current.getPath().equals(pathConfig.getPath())) {
+                    existingPath = current;
+                    break;
+                }
+            }
+
+            if (existingPath == null) {
+                paths.add(pathConfig);
+            } else {
+                existingPath.getMethods().addAll(pathConfig.getMethods());
+                existingPath.getScopes().addAll(pathConfig.getScopes());
+            }
         }
 
         return paths;
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index 563f7ca..c6adb9b 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -160,15 +160,25 @@
                         if (loginIframe.enable) {
                             setupCheckLoginIframe().success(function() {
                                 checkLoginIframe().success(function () {
+                                    kc.onAuthSuccess && kc.onAuthSuccess();
                                     initPromise.setSuccess();
                                 }).error(function () {
+                                    kc.onAuthError && kc.onAuthError();
                                     if (initOptions.onLoad) {
                                         onLoad();
                                     }
                                 });
                             });
                         } else {
-                            initPromise.setSuccess();
+                            kc.updateToken(-1).success(function() {
+                                kc.onAuthSuccess && kc.onAuthSuccess();
+                                initPromise.setSuccess();
+                            }).error(function() {
+                                kc.onAuthError && kc.onAuthError();
+                                if (initOptions.onLoad) {
+                                    onLoad();
+                                }
+                            });
                         }
                     } else if (initOptions.onLoad) {
                         onLoad();
@@ -368,7 +378,7 @@
             minValidity = minValidity || 5;
 
             var exec = function() {
-                if (!kc.isTokenExpired(minValidity)) {
+                if (minValidity >= 0 && !kc.isTokenExpired(minValidity)) {
                     promise.setSuccess(false);
                 } else {
                     var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
@@ -380,6 +390,7 @@
                         var req = new XMLHttpRequest();
                         req.open('POST', url, true);
                         req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+                        req.withCredentials = true;
 
                         if (kc.clientId && kc.clientSecret) {
                             req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
@@ -1055,7 +1066,7 @@
             if (!(this instanceof CookieStorage)) {
                 return new CookieStorage();
             }
-            
+
             var cs = this;
 
             cs.get = function(state) {
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
index 75de911..96c1d24 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
@@ -37,12 +37,10 @@ public class TimePolicyAdminResource implements PolicyProviderAdminService {
         String nbf = policy.getConfig().get("nbf");
         String noa = policy.getConfig().get("noa");
 
-        if (nbf == null && noa == null) {
-            throw new RuntimeException("You must provide NotBefore, NotOnOrAfter or both.");
+        if (nbf != null && noa != null) {
+            validateFormat(nbf);
+            validateFormat(noa);
         }
-
-        validateFormat(nbf);
-        validateFormat(noa);
     }
 
     @Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
index dc6af9f..3205cc5 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
@@ -22,8 +22,11 @@ import org.keycloak.authorization.policy.evaluation.Evaluation;
 import org.keycloak.authorization.policy.provider.PolicyProvider;
 
 import java.text.SimpleDateFormat;
+import java.util.Calendar;
 import java.util.Date;
 
+import static com.sun.corba.se.spi.activation.IIOP_CLEAR_TEXT.value;
+
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
@@ -45,9 +48,7 @@ public class TimePolicyProvider implements PolicyProvider {
     public void evaluate(Evaluation evaluation) {
         try {
             String notBefore = this.policy.getConfig().get("nbf");
-
             if (notBefore != null) {
-
                 if (this.currentDate.before(this.dateFormat.parse(format(notBefore)))) {
                     evaluation.deny();
                     return;
@@ -55,7 +56,6 @@ public class TimePolicyProvider implements PolicyProvider {
             }
 
             String notOnOrAfter = this.policy.getConfig().get("noa");
-
             if (notOnOrAfter != null) {
                 if (this.currentDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
                     evaluation.deny();
@@ -63,12 +63,48 @@ public class TimePolicyProvider implements PolicyProvider {
                 }
             }
 
+            if (isInvalid(Calendar.DAY_OF_MONTH, "dayMonth")
+                    || isInvalid(Calendar.MONTH, "month")
+                    || isInvalid(Calendar.YEAR, "year")
+                    || isInvalid(Calendar.HOUR_OF_DAY, "hour")
+                    || isInvalid(Calendar.MINUTE, "minute")) {
+                evaluation.deny();
+                return;
+            }
+
             evaluation.grant();
         } catch (Exception e) {
             throw new RuntimeException("Could not evaluate time-based policy [" + this.policy.getName() + "].", e);
         }
     }
 
+    private boolean isInvalid(int timeConstant, String configName) {
+        Calendar calendar = Calendar.getInstance();
+
+        calendar.setTime(this.currentDate);
+
+        int dateField = calendar.get(timeConstant);
+
+        if (Calendar.MONTH == timeConstant) {
+            dateField++;
+        }
+
+        String start = this.policy.getConfig().get(configName);
+        if (start != null) {
+            String end = this.policy.getConfig().get(configName + "End");
+            if (end != null) {
+                if (dateField < Integer.parseInt(start)  || dateField > Integer.parseInt(end)) {
+                    return true;
+                }
+            } else {
+                if (dateField != Integer.parseInt(start)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     static String format(String notBefore) {
         String trimmed = notBefore.trim();
 
diff --git a/core/src/main/java/org/keycloak/representations/UserInfo.java b/core/src/main/java/org/keycloak/representations/UserInfo.java
index 200e8e8..7849718 100755
--- a/core/src/main/java/org/keycloak/representations/UserInfo.java
+++ b/core/src/main/java/org/keycloak/representations/UserInfo.java
@@ -16,12 +16,31 @@
  */
 package org.keycloak.representations;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.keycloak.json.StringOrArrayDeserializer;
+import org.keycloak.json.StringOrArraySerializer;
 
 /**
  * @author pedroigor
  */
 public class UserInfo {
+
+    // Should be in signed UserInfo response
+    @JsonProperty("iss")
+    protected String issuer;
+    @JsonProperty("aud")
+    @JsonSerialize(using = StringOrArraySerializer.class)
+    @JsonDeserialize(using = StringOrArrayDeserializer.class)
+    protected String[] audience;
+
     @JsonProperty("sub")
     protected String sub;
 
@@ -85,6 +104,34 @@ public class UserInfo {
     @JsonProperty("claims_locales")
     protected String claimsLocales;
 
+    protected Map<String, Object> otherClaims = new HashMap<>();
+
+    public String getIssuer() {
+        return issuer;
+    }
+
+    public void setIssuer(String issuer) {
+        this.issuer = issuer;
+    }
+
+    @JsonIgnore
+    public String[] getAudience() {
+        return audience;
+    }
+
+    public boolean hasAudience(String audience) {
+        for (String a : this.audience) {
+            if (a.equals(audience)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setAudience(String... audience) {
+        this.audience = audience;
+    }
+
     public String getSubject() {
         return this.sub;
     }
@@ -260,4 +307,19 @@ public class UserInfo {
     public void setClaimsLocales(String claimsLocales) {
         this.claimsLocales = claimsLocales;
     }
+
+    /**
+     * This is a map of any other claims and data that might be in the UserInfo.  Could be custom claims set up by the auth server
+     *
+     * @return
+     */
+    @JsonAnyGetter
+    public Map<String, Object> getOtherClaims() {
+        return otherClaims;
+    }
+
+    @JsonAnySetter
+    public void setOtherClaims(String name, Object value) {
+        otherClaims.put(name, value);
+    }
 }
diff --git a/distribution/adapters/fuse-adapter-zip/pom.xml b/distribution/adapters/fuse-adapter-zip/pom.xml
new file mode 100644
index 0000000..c649720
--- /dev/null
+++ b/distribution/adapters/fuse-adapter-zip/pom.xml
@@ -0,0 +1,173 @@
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>keycloak-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>2.2.0-SNAPSHOT</version>
+        <relativePath>../../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>keycloak-fuse-adapter-dist</artifactId>
+    <packaging>pom</packaging>
+    <name>Keycloak Fuse Adapter Distro</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-osgi-features</artifactId>
+            <version>${project.version}</version>
+            <type>xml</type>
+            <classifier>features</classifier>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-osgi-thirdparty</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcprov-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.module</groupId>
+            <artifactId>jackson-module-jaxb-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-authz-client</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-adapter-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-osgi-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty-adapter-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty81-adapter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-osgi-jaas</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-jetty92-adapter</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-dependencies</id>
+                        <phase>prepare-package</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}/system</outputDirectory>
+                            <overWriteReleases>false</overWriteReleases>
+                            <overWriteSnapshots>false</overWriteSnapshots>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                            <useRepositoryLayout>true</useRepositoryLayout>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assemble</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <outputDirectory>target</outputDirectory>
+                            <workDirectory>target/assembly/work</workDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/distribution/adapters/pom.xml b/distribution/adapters/pom.xml
index cd72e9a..23d5135 100755
--- a/distribution/adapters/pom.xml
+++ b/distribution/adapters/pom.xml
@@ -32,6 +32,7 @@
 
     <modules>
         <module>as7-eap6-adapter</module>
+        <module>fuse-adapter-zip</module>
         <module>jetty81-adapter-zip</module>
         <module>jetty91-adapter-zip</module>
         <module>jetty92-adapter-zip</module>
diff --git a/distribution/demo-dist/pom.xml b/distribution/demo-dist/pom.xml
index 187d62d..71a5a1a 100755
--- a/distribution/demo-dist/pom.xml
+++ b/distribution/demo-dist/pom.xml
@@ -202,6 +202,31 @@
                     </execution>
                 </executions>
             </plugin>
+            
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>unpack</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-wildfly-server-subsystem</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <includes>default-config/*.xml</includes>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/distribution/demo-dist/src/main/xslt/standalone.xsl b/distribution/demo-dist/src/main/xslt/standalone.xsl
index 4ef3f0e..855efc0 100755
--- a/distribution/demo-dist/src/main/xslt/standalone.xsl
+++ b/distribution/demo-dist/src/main/xslt/standalone.xsl
@@ -1,19 +1,19 @@
 <!--
-  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
-  ~ and other contributors as indicated by the @author tags.
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
 
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:xalan="http://xml.apache.org/xalan"
@@ -42,7 +42,7 @@
     <xsl:template match="//ds:datasources">
         <xsl:copy>
             <xsl:apply-templates select="node()[name(.)='datasource']"/>
-            <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" use-java-context="true">
+            <datasource jndi-name="java:jboss/datasources/KeycloakDS" jta="false" pool-name="KeycloakDS" use-java-context="true">
                 <connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
                 <driver>h2</driver>
                 <security>
@@ -57,9 +57,7 @@
     <xsl:template match="//j:profile">
         <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
-            <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
-                <web-context>auth</web-context>
-            </subsystem>
+            <xsl:copy-of select="document('../../../target/dependency/default-config/keycloak-server-default-config.xml')"/>
             <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
             <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
         </xsl:copy>
diff --git a/distribution/downloads/pom.xml b/distribution/downloads/pom.xml
index e1356d6..71b27d9 100755
--- a/distribution/downloads/pom.xml
+++ b/distribution/downloads/pom.xml
@@ -262,6 +262,17 @@
                                     <artifactId>keycloak-wildfly-adapter-dist</artifactId>
                                     <type>tar.gz</type>
                                 </artifactItem>
+
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-fuse-adapter-dist</artifactId>
+                                    <type>zip</type>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-fuse-adapter-dist</artifactId>
+                                    <type>tar.gz</type>
+                                </artifactItem>
                             </artifactItems>
                             <outputDirectory>target/${project.version}/adapters/keycloak-oidc</outputDirectory>
                         </configuration>
diff --git a/distribution/feature-packs/server-feature-pack/assembly.xml b/distribution/feature-packs/server-feature-pack/assembly.xml
index 41ef173..861c698 100644
--- a/distribution/feature-packs/server-feature-pack/assembly.xml
+++ b/distribution/feature-packs/server-feature-pack/assembly.xml
@@ -59,15 +59,4 @@
             </includes>
         </fileSet>
     </fileSets>
-
-    <files>
-        <file>
-            <source>src/main/resources/content/standalone/configuration/keycloak-server.json</source>
-            <outputDirectory>content/domain/servers/server-one/configuration</outputDirectory>
-        </file>
-        <file>
-            <source>src/main/resources/content/standalone/configuration/keycloak-server.json</source>
-            <outputDirectory>content/domain/servers/server-two/configuration</outputDirectory>
-        </file>
-    </files>
 </assembly>
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml
index e769a7b..de03ed8 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-services/main/module.xml
@@ -55,6 +55,7 @@
         <module name="org.jboss.resteasy.resteasy-jaxrs"/>
         <module name="org.jboss.resteasy.resteasy-crypto"/>
         <module name="org.jboss.resteasy.resteasy-multipart-provider"/>
+        <module name="org.jboss.dmr"/>
         <module name="javax.servlet.api"/>
         <module name="com.fasterxml.jackson.core.jackson-core"/>
         <module name="com.fasterxml.jackson.core.jackson-annotations"/>
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-server-subsystem/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-server-subsystem/main/module.xml
index 9f44e59..d82e1a9 100644
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-server-subsystem/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/keycloak/org/keycloak/keycloak-wildfly-server-subsystem/main/module.xml
@@ -28,6 +28,8 @@
     </resources>
 
     <dependencies>
+        <module name="com.fasterxml.jackson.core.jackson-core"/>
+        <module name="com.fasterxml.jackson.core.jackson-databind"/>
         <module name="javax.api"/>
         <module name="org.jboss.staxmapper"/>
         <module name="org.jboss.as.controller"/>
diff --git a/distribution/server-overlay/assembly.xml b/distribution/server-overlay/assembly.xml
index 325cadf..162bd00 100755
--- a/distribution/server-overlay/assembly.xml
+++ b/distribution/server-overlay/assembly.xml
@@ -85,10 +85,6 @@
 
     <files>
         <file>
-            <source>${project.build.directory}/unpacked/keycloak-${project.version}/standalone/configuration/keycloak-server.json</source>
-            <outputDirectory>standalone/configuration</outputDirectory>
-        </file>
-        <file>
             <source>${project.build.directory}/unpacked/keycloak-${project.version}/bin/add-user-keycloak.sh</source>
             <outputDirectory>bin</outputDirectory>
             <destName>add-user-keycloak.sh</destName>
@@ -98,6 +94,11 @@
             <outputDirectory>bin</outputDirectory>
             <destName>add-user-keycloak.bat</destName>
         </file>
+        <file>
+            <source>${project.build.directory}/cli/default-keycloak-subsys-config.cli</source>
+            <outputDirectory>bin</outputDirectory>
+            <destName>default-keycloak-subsys-config.cli</destName>
+        </file>
     </files>
 
 </assembly>
diff --git a/distribution/server-overlay/cli/keycloak-install.cli b/distribution/server-overlay/cli/keycloak-install.cli
index c29cd5f..dbb2c32 100644
--- a/distribution/server-overlay/cli/keycloak-install.cli
+++ b/distribution/server-overlay/cli/keycloak-install.cli
@@ -1,5 +1,5 @@
 embed-server --server-config=standalone.xml
-/subsystem=datasources/data-source=KeycloakDS/:add(connection-url="jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE",driver-name=h2,jndi-name=java:jboss/datasources/KeycloakDS,password=sa,user-name=sa,use-java-context=true)
+/subsystem=datasources/data-source=KeycloakDS/:add(connection-url="jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE",jta=false,driver-name=h2,jndi-name=java:jboss/datasources/KeycloakDS,password=sa,user-name=sa,use-java-context=true)
 /subsystem=infinispan/cache-container=keycloak:add(jndi-name="infinispan/Keycloak")
 /subsystem=infinispan/cache-container=keycloak/local-cache=realms:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=users:add()
@@ -11,4 +11,4 @@ embed-server --server-config=standalone.xml
 /subsystem=infinispan/cache-container=keycloak/local-cache=authorization:add()
 /subsystem=infinispan/cache-container=keycloak/local-cache=authorization/eviction=EVICTION:add(max-entries=100,strategy=LRU)
 /extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem)
-/subsystem=keycloak-server:add(web-context=auth)
\ No newline at end of file
+run-batch --file=default-keycloak-subsys-config.cli
\ No newline at end of file
diff --git a/distribution/server-overlay/cli/keycloak-install-ha.cli b/distribution/server-overlay/cli/keycloak-install-ha.cli
index a84a34a..bc7d863 100644
--- a/distribution/server-overlay/cli/keycloak-install-ha.cli
+++ b/distribution/server-overlay/cli/keycloak-install-ha.cli
@@ -1,5 +1,5 @@
 embed-server --server-config=standalone-ha.xml
-/subsystem=datasources/data-source=KeycloakDS/:add(connection-url="jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE",driver-name=h2,jndi-name=java:jboss/datasources/KeycloakDS,password=sa,user-name=sa,use-java-context=true)
+/subsystem=datasources/data-source=KeycloakDS/:add(connection-url="jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE",jta=false,driver-name=h2,jndi-name=java:jboss/datasources/KeycloakDS,password=sa,user-name=sa,use-java-context=true)
 /subsystem=infinispan/cache-container=keycloak:add(jndi-name="infinispan/Keycloak")
 /subsystem=infinispan/cache-container=keycloak/transport=TRANSPORT:add(lock-timeout=60000)
 /subsystem=infinispan/cache-container=keycloak/invalidation-cache=realms:add(mode="SYNC")
@@ -11,4 +11,4 @@ embed-server --server-config=standalone-ha.xml
 /subsystem=infinispan/cache-container=keycloak/distributed-cache=authorization:add(mode="SYNC",owners="1")
 /subsystem=infinispan/cache-container=keycloak/replicated-cache=work:add(mode="SYNC")
 /extension=org.keycloak.keycloak-server-subsystem/:add(module=org.keycloak.keycloak-server-subsystem)
-/subsystem=keycloak-server:add(web-context=auth)
\ No newline at end of file
+run-batch --file=default-keycloak-subsys-config.cli
diff --git a/distribution/server-overlay/pom.xml b/distribution/server-overlay/pom.xml
index 96400d1..900bc29 100755
--- a/distribution/server-overlay/pom.xml
+++ b/distribution/server-overlay/pom.xml
@@ -46,6 +46,25 @@
                 <artifactId>maven-dependency-plugin</artifactId>
                 <executions>
                     <execution>
+                        <id>unpack</id>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-wildfly-server-subsystem</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>jar</type>
+                                    <includes>cli/*.cli</includes>
+                                    <outputDirectory>${project.build.directory}</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
                         <id>unpack-server-dist</id>
                         <phase>prepare-package</phase>
                         <goals>
diff --git a/examples/authz/photoz/photoz-restful-api/pom.xml b/examples/authz/photoz/photoz-restful-api/pom.xml
index ba7a880..7622af4 100755
--- a/examples/authz/photoz/photoz-restful-api/pom.xml
+++ b/examples/authz/photoz/photoz-restful-api/pom.xml
@@ -40,6 +40,12 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>1.0-SP4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-authz-client</artifactId>
             <version>${project.version}</version>
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java
index b349e02..428ba07 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java
+++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java
@@ -19,9 +19,8 @@ package org.keycloak.example.photoz.admin;
 
 import org.keycloak.example.photoz.entity.Album;
 
-import javax.ejb.Stateless;
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -36,12 +35,11 @@ import java.util.List;
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 @Path("/admin/album")
-@Stateless
 public class AdminAlbumService {
 
     public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage";
 
-    @PersistenceContext
+    @Inject
     private EntityManager entityManager;
 
     @Context
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java
index a5d7f16..d0e9c2d 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java
+++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java
@@ -7,10 +7,12 @@ import org.keycloak.authorization.client.representation.ScopeRepresentation;
 import org.keycloak.authorization.client.resource.ProtectionResource;
 import org.keycloak.example.photoz.ErrorResponse;
 import org.keycloak.example.photoz.entity.Album;
+import org.keycloak.example.photoz.util.Transaction;
 import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.util.JsonSerialization;
 
 import javax.ejb.Stateless;
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
@@ -31,14 +33,14 @@ import java.util.List;
 import java.util.Set;
 
 @Path("/album")
-@Stateless
+@Transaction
 public class AlbumService {
 
     public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view";
     public static final String SCOPE_ALBUM_CREATE = "urn:photoz.com:scopes:album:create";
     public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete";
 
-    @PersistenceContext
+    @Inject
     private EntityManager entityManager;
 
     @Context
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java
index be638b6..f7b55cb 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java
+++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java
@@ -18,6 +18,7 @@
 package org.keycloak.example.photoz.album;
 
 import javax.ejb.Stateless;
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.servlet.http.HttpServletRequest;
@@ -34,12 +35,11 @@ import java.util.List;
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 @Path("/profile")
-@Stateless
 public class ProfileService {
 
     private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view";
 
-    @PersistenceContext
+    @Inject
     private EntityManager entityManager;
 
     @GET
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java
new file mode 100644
index 0000000..c917da2
--- /dev/null
+++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.photoz.util;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Produces;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@ApplicationScoped
+public class Resources {
+
+    private EntityManagerFactory entityManagerFactory;
+
+    @PostConstruct
+    public void init() {
+        entityManagerFactory = Persistence.createEntityManagerFactory("primary");
+    }
+
+    @PreDestroy
+    public void dispose() {
+        entityManagerFactory.close();
+    }
+
+    @RequestScoped
+    @Produces
+    public EntityManager createEntityManager() {
+        return entityManagerFactory.createEntityManager();
+    }
+}
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java
new file mode 100644
index 0000000..a3caa78
--- /dev/null
+++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.photoz.util;
+
+import javax.interceptor.InterceptorBinding;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@InterceptorBinding
+@Target({ TYPE })
+@Retention(RUNTIME)
+public @interface Transaction {
+}
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java
new file mode 100644
index 0000000..36d35f3
--- /dev/null
+++ b/examples/authz/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.photoz.util;
+
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@Interceptor
+@Transaction
+public class TransactionInterceptor {
+
+    @Inject
+    private Instance<EntityManager> entityManager;
+
+    @AroundInvoke
+    public Object aroundInvoke(InvocationContext context) {
+        EntityManager entityManager = this.entityManager.get();
+        EntityTransaction transaction = entityManager.getTransaction();
+
+        try {
+            transaction.begin();
+            Object proceed = context.proceed();
+            transaction.commit();
+            return proceed;
+        } catch (Exception cause) {
+            if (transaction != null && transaction.isActive()) {
+                transaction.rollback();
+            }
+            throw new RuntimeException(cause);
+        } finally {
+            entityManager.close();
+        }
+    }
+}
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml
index 957dc8a..fbf2a32 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml
+++ b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml
@@ -3,5 +3,7 @@
    xsi:schemaLocation="
         http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
-        
+    <interceptors>
+        <class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
+    </interceptors>
 </beans>
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml
index 9323182..c15d34f 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml
+++ b/examples/authz/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml
@@ -4,14 +4,18 @@
 	xsi:schemaLocation="
         http://java.sun.com/xml/ns/persistence
         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
-	<persistence-unit name="primary">
-		<non-jta-data-source>java:jboss/datasources/PhotozDS</non-jta-data-source>
+	<persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
 
 		<class>org.keycloak.example.photoz.entity.Album</class>
 		<class>org.keycloak.example.photoz.entity.Photo</class>
 
 		<properties>
-			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+			<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
+			<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
+			<property name="hibernate.connection.url" value="jdbc:h2:~/keycloak-photoz-example" />
+			<property name="hibernate.connection.user" value="sa" />
+			<property name="hibernate.flushMode" value="FLUSH_AUTO" />
 			<property name="hibernate.hbm2ddl.auto" value="update" />
 			<property name="hibernate.show_sql" value="false" />
 		</properties>
diff --git a/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml b/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml
index 4b23be6..4553358 100644
--- a/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml
+++ b/examples/authz/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml
@@ -20,6 +20,7 @@
     <deployment>
         <dependencies>
             <module name="org.keycloak.keycloak-authz-client" services="import"/>
+            <module name="com.h2database.h2" services="import"/>
         </dependencies>
     </deployment>
 </jboss-deployment-structure>
diff --git a/examples/broker/google-authentication/README.md b/examples/broker/google-authentication/README.md
index 0825aed..48ddca7 100644
--- a/examples/broker/google-authentication/README.md
+++ b/examples/broker/google-authentication/README.md
@@ -3,7 +3,7 @@
 What is it?
 -----------
 
-This example demonstrates how to use Social Ientity Providers with Keycloak to authenticate users. In this case,
+This example demonstrates how to use Social Identity Providers with Keycloak to authenticate users. In this case,
 users are authenticated with Google using Keycloak Identity Broker capabilities using the oAuth 2 protocol.
 
 From this example, you'll learn how to:
@@ -180,4 +180,4 @@ Debug the Application
 If you want to debug the source code or look at the Javadocs of any library in the project, run either of the following commands to pull them into your local repository. The IDE should then detect them.
 
         mvn dependency:sources
-        mvn dependency:resolve -Dclassifier=javadoc
\ No newline at end of file
+        mvn dependency:resolve -Dclassifier=javadoc
diff --git a/examples/broker/twitter-authentication/README.md b/examples/broker/twitter-authentication/README.md
index 5e93083..8f33d2b 100644
--- a/examples/broker/twitter-authentication/README.md
+++ b/examples/broker/twitter-authentication/README.md
@@ -3,7 +3,7 @@
 What is it?
 -----------
 
-This example demonstrates how to use Social Ientity Providers with Keycloak to authenticate users. In this case,
+This example demonstrates how to use Social Identity Providers with Keycloak to authenticate users. In this case,
 users are authenticated with Twitter using Keycloak Identity Broker capabilities using the oAuth 2 protocol.
 
 From this example, you'll learn how to:
@@ -179,4 +179,4 @@ Debug the Application
 If you want to debug the source code or look at the Javadocs of any library in the project, run either of the following commands to pull them into your local repository. The IDE should then detect them.
 
         mvn dependency:sources
-        mvn dependency:resolve -Dclassifier=javadoc
\ No newline at end of file
+        mvn dependency:resolve -Dclassifier=javadoc
diff --git a/misc/UpdatingServerConfig.md b/misc/UpdatingServerConfig.md
new file mode 100644
index 0000000..a3282af
--- /dev/null
+++ b/misc/UpdatingServerConfig.md
@@ -0,0 +1,65 @@
+# Changing the Default *keycloak-subsystem* Configuration
+
+If you need to make a change to the default keycloak-subsystem 
+configuration that is packaged with our distributions, you will need to edit this file:
+https://github.com/keycloak/keycloak/blob/master/wildfly/server-subsystem/src/main/config/default-server-subsys-config.properties
+
+This file contains a single multi-line property containing the subsystem 
+xml declaration.  Maven filtering is used to read this property and 
+inject it everywhere it needs to go.  Editing this file will also take 
+care of propagating it to the distributions like server-dist and demo-dist.
+
+Also, you need to create CLI commands for each change by editing this file:
+https://github.com/keycloak/keycloak/blob/master/wildfly/server-subsystem/src/main/resources/cli/default-keycloak-subsys-config.cli
+
+This CLI snippet is used in the scripts required by the overlay distribution.
+
+## Updating an SPI
+The changes you will likely make are when you need to add a new SPI, change an existing SPI, or add/change a provider within an SPI.
+
+All elements in an SPI declaration are optional, but a full SPI declaration
+  looks like this:
+````xml
+<spi name="dblock">
+     <default-provider>mongo</default-provider>
+     <provider name="jpa" enabled="true">
+         <properties>
+             <property name="lockWaitTimeout" value="800"/>
+         </properties>
+     </provider>
+     <provider name="mongo" enabled="true">
+         <properties>
+             <property name="lockRecheckTime" value="2"/>
+             <property name="lockWaitTimeout" value="600"/>
+         </properties>
+     </provider>
+</spi>
+````
+Here we have two providers defined for the SPI `dblock`.  The 
+`default-provider` is listed as `mongo`.  However it is up to the SPI to decide how it will 
+treat this setting.  Some SPIs allow more than one provider and some do not.  So
+`default-provider` can help the SPI to choose.
+
+Also notice that each provider defines its own set of configuration 
+properties.  The fact that both providers above have a property called 
+`lockWaitTimeout` is just a coincidence.
+
+## Values of type *List*
+The type of each property value is interpreted by the provider. However, 
+there is one exception.  Consider the `jpa` provider for the `eventStore` API:
+````xml
+<spi name="eventsStore">
+     <provider name="jpa" enabled="true">
+         <properties>
+             <property name="exclude-events" value="[&quot;EVENT1&quot;,&quot;EVENT2&quot;]"/>
+         </properties>
+     </provider>
+</spi>
+````
+We see that the value begins and ends with square brackets.  That means that
+the value will be passed to the provider as a list.  In this example, 
+the system will pass the
+provider a list with two element values `EVENT1` and `EVENT2`. To add 
+more values to the list, just separate each list element with a comma. Unfortunately,
+you do need to escape the quotes surrounding each list element with 
+`&quot;`.
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
index 4657633..b503bce 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedPolicyStore.java
@@ -104,6 +104,11 @@ public class CachedPolicyStore implements PolicyStore {
     }
 
     @Override
+    public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
+    }
+
+    @Override
     public List<Policy> findByResource(String resourceId) {
         List<Policy> cache = new ArrayList<>();
 
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
index 4d9a946..f86de2f 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedResourceStore.java
@@ -32,6 +32,7 @@ import org.keycloak.models.authorization.infinispan.entities.CachedResource;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -127,6 +128,11 @@ public class CachedResourceStore implements ResourceStore {
     }
 
     @Override
+    public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
+    }
+
+    @Override
     public List<Resource> findByScope(String... id) {
         return getDelegate().findByScope(id).stream().map(resource -> findById(resource.getId())).collect(Collectors.toList());
     }
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
index 72f3f25..f86a7d1 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/CachedScopeStore.java
@@ -30,6 +30,7 @@ import org.keycloak.models.authorization.infinispan.entities.CachedScope;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 
 /**
@@ -114,6 +115,11 @@ public class CachedScopeStore implements ScopeStore {
         return getDelegate().findByResourceServer(id);
     }
 
+    @Override
+    public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
+    }
+
     private String getCacheKeyForScope(String id) {
         return SCOPE_ID_CACHE_PREFIX + id;
     }
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java
index 8b88ad1..b57cd1e 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAPolicyStore.java
@@ -27,11 +27,15 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.Query;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -101,6 +105,43 @@ public class JPAPolicyStore implements PolicyStore {
     }
 
     @Override
+    public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<PolicyEntity> querybuilder = builder.createQuery(PolicyEntity.class);
+        Root<PolicyEntity> root = querybuilder.from(PolicyEntity.class);
+        List<Predicate> predicates = new ArrayList();
+
+        predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
+
+        attributes.forEach((name, value) -> {
+            if ("permission".equals(name)) {
+                if (Boolean.valueOf(value[0])) {
+                    predicates.add(root.get("type").in("resource", "scope"));
+                } else {
+                    predicates.add(builder.not(root.get("type").in("resource", "scope")));
+                }
+            } else if ("id".equals(name)) {
+                predicates.add(root.get(name).in(value));
+            } else {
+                predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
+            }
+        });
+
+        querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
+
+        Query query = entityManager.createQuery(querybuilder);
+
+        if (firstResult != -1) {
+            query.setFirstResult(firstResult);
+        }
+        if (maxResult != -1) {
+            query.setMaxResults(maxResult);
+        }
+
+        return query.getResultList();
+    }
+
+    @Override
     public List<Policy> findByResource(final String resourceId) {
         Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.resources r where r.id = :resourceId");
 
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java
index 986d007..6d00bb6 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAResourceStore.java
@@ -26,8 +26,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Query;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -97,6 +103,37 @@ public class JPAResourceStore implements ResourceStore {
     }
 
     @Override
+    public List findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<ResourceEntity> querybuilder = builder.createQuery(ResourceEntity.class);
+        Root<ResourceEntity> root = querybuilder.from(ResourceEntity.class);
+        List<Predicate> predicates = new ArrayList();
+
+        predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
+
+        attributes.forEach((name, value) -> {
+            if ("scope".equals(name)) {
+                predicates.add(root.join("scopes").get("id").in(value));
+            } else {
+                predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
+            }
+        });
+
+        querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
+
+        Query query = entityManager.createQuery(querybuilder);
+
+        if (firstResult != -1) {
+            query.setFirstResult(firstResult);
+        }
+        if (maxResult != -1) {
+            query.setMaxResults(maxResult);
+        }
+
+        return query.getResultList();
+    }
+
+    @Override
     public List<Resource> findByScope(String... id) {
         Query query = entityManager.createQuery("select r from ResourceEntity r inner join r.scopes s where s.id in (:scopeIds)");
 
diff --git a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java
index cc9a956..d468314 100644
--- a/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java
+++ b/model/jpa/src/main/java/org/keycloak/authorization/jpa/store/JPAScopeStore.java
@@ -27,7 +27,13 @@ import org.keycloak.models.utils.KeycloakModelUtils;
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.Query;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -85,4 +91,31 @@ public class JPAScopeStore implements ScopeStore {
 
         return query.getResultList();
     }
+
+    @Override
+    public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+        CriteriaQuery<ScopeEntity> querybuilder = builder.createQuery(ScopeEntity.class);
+        Root<ScopeEntity> root = querybuilder.from(ScopeEntity.class);
+        List<Predicate> predicates = new ArrayList();
+
+        predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
+
+        attributes.forEach((name, value) -> {
+            predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
+        });
+
+        querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
+
+        Query query = entityManager.createQuery(querybuilder);
+
+        if (firstResult != -1) {
+            query.setFirstResult(firstResult);
+        }
+        if (maxResult != -1) {
+            query.setMaxResults(maxResult);
+        }
+
+        return query.getResultList();
+    }
 }
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index 4272fb8..3c74264 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.connections.jpa;
 
+import java.io.File;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.DriverManager;
@@ -42,6 +43,7 @@ import org.keycloak.models.dblock.DBLockProvider;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.provider.ServerInfoAwareProviderFactory;
 import org.keycloak.models.dblock.DBLockManager;
+import org.keycloak.ServerStartupError;
 import org.keycloak.timer.TimerProvider;
 
 /**
@@ -51,6 +53,10 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
 
     private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class);
 
+    enum MigrationStrategy {
+        UPDATE, VALIDATE, MANUAL
+    }
+
     private volatile EntityManagerFactory emf;
 
     private Config.Scope config;
@@ -125,22 +131,9 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
                         properties.put(JpaUtils.HIBERNATE_DEFAULT_SCHEMA, schema);
                     }
 
-
-                    String databaseSchema;
-                    String databaseSchemaConf = config.get("databaseSchema");
-                    if (databaseSchemaConf == null) {
-                        throw new RuntimeException("Property 'databaseSchema' needs to be specified in the configuration");
-                    }
-                    
-                    if (databaseSchemaConf.equals("development-update")) {
-                        properties.put("hibernate.hbm2ddl.auto", "update");
-                        databaseSchema = null;
-                    } else if (databaseSchemaConf.equals("development-validate")) {
-                        properties.put("hibernate.hbm2ddl.auto", "validate");
-                        databaseSchema = null;
-                    } else {
-                        databaseSchema = databaseSchemaConf;
-                    }
+                    MigrationStrategy migrationStrategy = getMigrationStrategy();
+                    boolean initializeEmpty = config.getBoolean("initializeEmpty", true);
+                    File databaseUpdateFile = getDatabaseUpdateFile();
 
                     properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
                     properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
@@ -153,39 +146,8 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
                         if (driverDialect != null) {
                             properties.put("hibernate.dialect", driverDialect);
                         }
-	                    
-	                    if (databaseSchema != null) {
-	                        logger.trace("Updating database");
-	
-	                        JpaUpdaterProvider updater = session.getProvider(JpaUpdaterProvider.class);
-	                        if (updater == null) {
-	                            throw new RuntimeException("Can't update database: JPA updater provider not found");
-	                        }
 
-                            // Check if having DBLock before trying to initialize hibernate
-                            DBLockProvider dbLock = new DBLockManager(session).getDBLock();
-                            if (dbLock.hasLock()) {
-                                updateOrValidateDB(databaseSchema, connection, updater, schema);
-                            } else {
-                                logger.trace("Don't have DBLock retrieved before upgrade. Needs to acquire lock first in separate transaction");
-
-                                KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
-
-                                    @Override
-                                    public void run(KeycloakSession lockSession) {
-                                        DBLockManager dbLockManager = new DBLockManager(lockSession);
-                                        DBLockProvider dbLock2 = dbLockManager.getDBLock();
-                                        dbLock2.waitForLock();
-                                        try {
-                                            updateOrValidateDB(databaseSchema, connection, updater, schema);
-                                        } finally {
-                                            dbLock2.releaseLock();
-                                        }
-                                    }
-
-                                });
-                            }
-	                    }
+                        migration(migrationStrategy, initializeEmpty, schema, databaseUpdateFile, connection, session);
 
                         int globalStatsInterval = config.getInt("globalStatsInterval", -1);
                         if (globalStatsInterval != -1) {
@@ -199,18 +161,6 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
                         if (globalStatsInterval != -1) {
                             startGlobalStats(session, globalStatsInterval);
                         }
-
-                    } catch (Exception e) {
-                        // Safe rollback
-                        if (connection != null) {
-                            try {
-                                connection.rollback();
-                            } catch (SQLException e2) {
-                                logger.warn("Can't rollback connection", e2);
-                            }
-                        }
-
-                        throw e;
                     } finally {
 	                    // Close after creating EntityManagerFactory to prevent in-mem databases from closing
 	                    if (connection != null) {
@@ -226,6 +176,11 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
         }
     }
 
+    private File getDatabaseUpdateFile() {
+        String databaseUpdateFile = config.get("migrationExport", "keycloak-database-update.sql");
+        return new File(databaseUpdateFile);
+    }
+
     protected void prepareOperationalInfo(Connection connection) {
   		try {
   			operationalInfo = new LinkedHashMap<>();
@@ -282,20 +237,82 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
         timer.scheduleTask(new HibernateStatsReporter(emf), globalStatsIntervalSecs * 1000, "ReportHibernateGlobalStats");
     }
 
+    public void migration(MigrationStrategy strategy, boolean initializeEmpty, String schema, File databaseUpdateFile, Connection connection, KeycloakSession session) {
+        JpaUpdaterProvider updater = session.getProvider(JpaUpdaterProvider.class);
+
+        JpaUpdaterProvider.Status status = updater.validate(connection, schema);
+        if (status == JpaUpdaterProvider.Status.VALID) {
+            logger.debug("Database is up-to-date");
+        } else if (status == JpaUpdaterProvider.Status.EMPTY) {
+            if (initializeEmpty) {
+                update(connection, schema, session, updater);
+            } else {
+                switch (strategy) {
+                    case UPDATE:
+                        update(connection, schema, session, updater);
+                        break;
+                    case MANUAL:
+                        export(connection, schema, databaseUpdateFile, session, updater);
+                        throw new ServerStartupError("Database not initialized, please initialize database with " + databaseUpdateFile.getAbsolutePath(), false);
+                    case VALIDATE:
+                        throw new ServerStartupError("Database not initialized, please enable database initialization", false);
+                }
+            }
+        } else {
+            switch (strategy) {
+                case UPDATE:
+                    update(connection, schema, session, updater);
+                    break;
+                case MANUAL:
+                    export(connection, schema, databaseUpdateFile, session, updater);
+                    throw new ServerStartupError("Database not up-to-date, please migrate database with " + databaseUpdateFile.getAbsolutePath(), false);
+                case VALIDATE:
+                    throw new ServerStartupError("Database not up-to-date, please enable database migration", false);
+            }
+        }
+    }
 
-    // Needs to be called with acquired DBLock
-    protected void updateOrValidateDB(String databaseSchema, Connection connection, JpaUpdaterProvider updater, String schema) {
-        if (databaseSchema.equals("update")) {
+    protected void update(Connection connection, String schema, KeycloakSession session, JpaUpdaterProvider updater) {
+        DBLockProvider dbLock = new DBLockManager(session).getDBLock();
+        if (dbLock.hasLock()) {
             updater.update(connection, schema);
-            logger.trace("Database update completed");
-        } else if (databaseSchema.equals("validate")) {
-            updater.validate(connection, schema);
-            logger.trace("Database validation completed");
         } else {
-            throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
+            KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
+                @Override
+                public void run(KeycloakSession lockSession) {
+                    DBLockManager dbLockManager = new DBLockManager(lockSession);
+                    DBLockProvider dbLock2 = dbLockManager.getDBLock();
+                    dbLock2.waitForLock();
+                    try {
+                        updater.update(connection, schema);
+                    } finally {
+                        dbLock2.releaseLock();
+                    }
+                }
+            });
         }
     }
 
+    protected void export(Connection connection, String schema, File databaseUpdateFile, KeycloakSession session, JpaUpdaterProvider updater) {
+        DBLockProvider dbLock = new DBLockManager(session).getDBLock();
+        if (dbLock.hasLock()) {
+            updater.export(connection, schema, databaseUpdateFile);
+        } else {
+            KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
+                @Override
+                public void run(KeycloakSession lockSession) {
+                    DBLockManager dbLockManager = new DBLockManager(lockSession);
+                    DBLockProvider dbLock2 = dbLockManager.getDBLock();
+                    dbLock2.waitForLock();
+                    try {
+                        updater.export(connection, schema, databaseUpdateFile);
+                    } finally {
+                        dbLock2.releaseLock();
+                    }
+                }
+            });
+        }
+    }
 
     @Override
     public Connection getConnection() {
@@ -323,4 +340,18 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
   		return operationalInfo;
   	}
 
+    private MigrationStrategy getMigrationStrategy() {
+        String migrationStrategy = config.get("migrationStrategy");
+        if (migrationStrategy == null) {
+            // Support 'databaseSchema' for backwards compatibility
+            migrationStrategy = config.get("databaseSchema");
+        }
+
+        if (migrationStrategy != null) {
+            return MigrationStrategy.valueOf(migrationStrategy.toUpperCase());
+        } else {
+            return MigrationStrategy.UPDATE;
+        }
+    }
+
 }
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java
index b087535..37228e3 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java
@@ -19,6 +19,7 @@ package org.keycloak.connections.jpa.updater;
 
 import org.keycloak.provider.Provider;
 
+import java.io.File;
 import java.sql.Connection;
 
 /**
@@ -26,10 +27,14 @@ import java.sql.Connection;
  */
 public interface JpaUpdaterProvider extends Provider {
 
-    public String FIRST_VERSION = "1.0.0.Final";
+    enum Status {
+        VALID, EMPTY, OUTDATED
+    }
 
-    public void update(Connection connection, String defaultSchema);
+    void update(Connection connection, String defaultSchema);
 
-    public void validate(Connection connection, String defaultSchema);
+    Status validate(Connection connection, String defaultSchema);
+
+    void export(Connection connection, String defaultSchema, File file);
 
 }
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
index 2610174..b4a50a9 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
@@ -30,6 +30,9 @@ import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionPr
 import org.keycloak.connections.jpa.util.JpaUtils;
 import org.keycloak.models.KeycloakSession;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.lang.reflect.Method;
 import java.sql.Connection;
 import java.util.List;
@@ -53,6 +56,15 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
 
     @Override
     public void update(Connection connection, String defaultSchema) {
+        update(connection, null, defaultSchema);
+    }
+
+    @Override
+    public void export(Connection connection, String defaultSchema, File file) {
+        update(connection, file, defaultSchema);
+    }
+
+    private void update(Connection connection, File file, String defaultSchema) {
         logger.debug("Starting database update");
 
         // Need ThreadLocal as liquibase doesn't seem to have API to inject custom objects into tasks
@@ -61,7 +73,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
         try {
             // Run update with keycloak master changelog first
             Liquibase liquibase = getLiquibaseForKeycloakUpdate(connection, defaultSchema);
-            updateChangeSet(liquibase, liquibase.getChangeLogFile());
+            updateChangeSet(liquibase, liquibase.getChangeLogFile(), file);
 
             // Run update for each custom JpaEntityProvider
             Set<JpaEntityProvider> jpaProviders = session.getAllProviders(JpaEntityProvider.class);
@@ -71,7 +83,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
                     String factoryId = jpaProvider.getFactoryId();
                     String changelogTableName = JpaUtils.getCustomChangelogTableName(factoryId);
                     liquibase = getLiquibaseForCustomProviderUpdate(connection, defaultSchema, customChangelog, jpaProvider.getClass().getClassLoader(), changelogTableName);
-                    updateChangeSet(liquibase, liquibase.getChangeLogFile());
+                    updateChangeSet(liquibase, liquibase.getChangeLogFile(), file);
                 }
             }
         } catch (Exception e) {
@@ -81,7 +93,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
         }
     }
 
-    protected void updateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException {
+
+    protected void updateChangeSet(Liquibase liquibase, String changelog, File exportFile) throws LiquibaseException, IOException {
         List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null);
         if (!changeSets.isEmpty()) {
             List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
@@ -95,7 +108,12 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
                 }
             }
 
-            liquibase.update((Contexts) null);
+            if (exportFile != null) {
+                liquibase.update((Contexts) null, new FileWriter(exportFile));
+            } else {
+                liquibase.update((Contexts) null);
+            }
+
             logger.debugv("Completed database update for changelog {0}", changelog);
         } else {
             logger.debugv("Database is up to date for changelog {0}", changelog);
@@ -107,13 +125,18 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
     }
 
     @Override
-    public void validate(Connection connection, String defaultSchema) {
+    public Status validate(Connection connection, String defaultSchema) {
         logger.debug("Validating if database is updated");
+        ThreadLocalSessionContext.setCurrentSession(session);
 
         try {
             // Validate with keycloak master changelog first
             Liquibase liquibase = getLiquibaseForKeycloakUpdate(connection, defaultSchema);
-            validateChangeSet(liquibase, liquibase.getChangeLogFile());
+
+            Status status = validateChangeSet(liquibase, liquibase.getChangeLogFile());
+            if (status != Status.VALID) {
+                return status;
+            }
 
             // Validate each custom JpaEntityProvider
             Set<JpaEntityProvider> jpaProviders = session.getAllProviders(JpaEntityProvider.class);
@@ -123,24 +146,30 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
                     String factoryId = jpaProvider.getFactoryId();
                     String changelogTableName = JpaUtils.getCustomChangelogTableName(factoryId);
                     liquibase = getLiquibaseForCustomProviderUpdate(connection, defaultSchema, customChangelog, jpaProvider.getClass().getClassLoader(), changelogTableName);
-                    validateChangeSet(liquibase, liquibase.getChangeLogFile());
+                    if (validateChangeSet(liquibase, liquibase.getChangeLogFile()) != Status.VALID) {
+                        return Status.OUTDATED;
+                    }
                 }
             }
-
         } catch (LiquibaseException e) {
             throw new RuntimeException("Failed to validate database", e);
         }
+
+        return Status.VALID;
     }
 
-    protected void validateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException {
+    protected Status validateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException {
         List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null);
         if (!changeSets.isEmpty()) {
-            List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
-            String errorMessage = String.format("Failed to validate database schema. Schema needs updating database from %s to %s. Please change databaseSchema to 'update' or use other database. Used changelog was %s",
-                    ranChangeSets.get(ranChangeSets.size() - 1).getId(), changeSets.get(changeSets.size() - 1).getId(), changelog);
-            throw new RuntimeException(errorMessage);
+            if (changeSets.size() == liquibase.getDatabaseChangeLog().getChangeSets().size()) {
+                return Status.EMPTY;
+            } else {
+                logger.debugf("Validation failed. Database is not up-to-date for changelog %s", changelog);
+                return Status.OUTDATED;
+            }
         } else {
             logger.debugf("Validation passed. Database is up-to-date for changelog %s", changelog);
+            return Status.VALID;
         }
     }
 
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
index 8e126e5..e1a546e 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/ClientAdapter.java
@@ -498,6 +498,18 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
     @Override
     public void updateClient() {
         em.flush();
+        session.getKeycloakSessionFactory().publish(new RealmModel.ClientUpdatedEvent() {
+
+            @Override
+            public ClientModel getUpdatedClient() {
+                return ClientAdapter.this;
+            }
+
+            @Override
+            public KeycloakSession getKeycloakSession() {
+                return session;
+            }
+        });
     }
 
     @Override
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java
index 6f0ba5d..04a3d9a 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoPolicyStore.java
@@ -32,6 +32,8 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
 
 import static java.util.stream.Collectors.toList;
 
@@ -102,6 +104,31 @@ public class MongoPolicyStore implements PolicyStore {
     }
 
     @Override
+    public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        QueryBuilder queryBuilder = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId);
+
+        attributes.forEach((name, value) -> {
+            if ("permission".equals(name)) {
+                if (Boolean.valueOf(value[0])) {
+                    queryBuilder.and("type").in(new String[] {"resource", "scope"});
+                } else {
+                    queryBuilder.and("type").notIn(new String[] {"resource", "scope"});
+                }
+            } else if ("id".equals(name)) {
+                queryBuilder.and("_id").in(value);
+            } else {
+                queryBuilder.and(name).regex(Pattern.compile(".*" + value[0] + ".*", Pattern.CASE_INSENSITIVE));
+            }
+        });
+
+        DBObject sort = new BasicDBObject("name", 1);
+
+        return getMongoStore().loadEntities(PolicyEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
+                .map(policy -> findById(policy.getId())).collect(toList());
+    }
+
+    @Override
     public List<Policy> findByResource(String resourceId) {
         DBObject query = new QueryBuilder()
                 .and("resources").is(resourceId)
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java
index 11b735b..a85de72 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoResourceStore.java
@@ -18,6 +18,7 @@
 
 package org.keycloak.authorization.mongo.store;
 
+import com.mongodb.BasicDBObject;
 import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.keycloak.authorization.AuthorizationProvider;
@@ -26,12 +27,13 @@ import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.mongo.adapter.ResourceAdapter;
 import org.keycloak.authorization.mongo.entities.ResourceEntity;
 import org.keycloak.authorization.store.ResourceStore;
-import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
 import org.keycloak.connections.mongo.api.MongoStore;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
 
 import static java.util.stream.Collectors.toList;
 
@@ -99,9 +101,28 @@ public class MongoResourceStore implements ResourceStore {
     }
 
     @Override
+    public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        QueryBuilder queryBuilder = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId);
+
+        attributes.forEach((name, value) -> {
+            if ("scope".equals(name)) {
+                queryBuilder.and("scopes").in(value);
+            } else {
+                queryBuilder.and(name).regex(Pattern.compile(".*" + value[0] + ".*", Pattern.CASE_INSENSITIVE));
+            }
+        });
+
+        DBObject sort = new BasicDBObject("name", 1);
+
+        return getMongoStore().loadEntities(ResourceEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
+                .map(scope -> findById(scope.getId())).collect(toList());
+    }
+
+    @Override
     public List<Resource> findByScope(String... id) {
         DBObject query = new QueryBuilder()
-                .and("scopes.id").in(id)
+                .and("scopes").in(id)
                 .get();
 
         return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
diff --git a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java
index e57b69b..4b7edd6 100644
--- a/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java
+++ b/model/mongo/src/main/java/org/keycloak/authorization/mongo/store/MongoScopeStore.java
@@ -18,6 +18,7 @@
 
 package org.keycloak.authorization.mongo.store;
 
+import com.mongodb.BasicDBObject;
 import com.mongodb.DBObject;
 import com.mongodb.QueryBuilder;
 import org.keycloak.authorization.AuthorizationProvider;
@@ -31,6 +32,8 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.utils.KeycloakModelUtils;
 
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
 
 import static java.util.stream.Collectors.toList;
 
@@ -98,6 +101,21 @@ public class MongoScopeStore implements ScopeStore {
                 .collect(toList());
     }
 
+    @Override
+    public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
+        QueryBuilder queryBuilder = new QueryBuilder()
+                .and("resourceServerId").is(resourceServerId);
+
+        attributes.forEach((name, value) -> {
+            queryBuilder.and(name).regex(Pattern.compile(".*" + value[0] + ".*", Pattern.CASE_INSENSITIVE));
+        });
+
+        DBObject sort = new BasicDBObject("name", 1);
+
+        return getMongoStore().loadEntities(ScopeEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
+                .map(scope -> findById(scope.getId())).collect(toList());
+    }
+
     private MongoStoreInvocationContext getInvocationContext() {
         return this.invocationContext;
     }
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index b899e0d..ce09046 100755
--- a/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -51,6 +51,10 @@ import com.mongodb.ServerAddress;
  */
 public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory, ServerInfoAwareProviderFactory {
 
+    enum MigrationStrategy {
+        UPDATE, VALIDATE
+    }
+
     // TODO Make it dynamic
     private String[] entities = new String[]{
             "org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity",
@@ -165,46 +169,34 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
     }
 
     private void update(KeycloakSession session) {
-        String databaseSchema = config.get("databaseSchema");
+        MigrationStrategy strategy = getMigrationStrategy();
+
+        MongoUpdaterProvider mongoUpdater = session.getProvider(MongoUpdaterProvider.class);
+        if (mongoUpdater == null) {
+            throw new RuntimeException("Can't update database: Mongo updater provider not found");
+        }
 
-        if (databaseSchema == null) {
-            throw new RuntimeException("Property 'databaseSchema' needs to be specified in the configuration of mongo connections");
+        DBLockProvider dbLock = new DBLockManager(session).getDBLock();
+        if (dbLock.hasLock()) {
+            updateOrValidateDB(strategy, session, mongoUpdater);
         } else {
-            MongoUpdaterProvider mongoUpdater = session.getProvider(MongoUpdaterProvider.class);
-            if (mongoUpdater == null) {
-                throw new RuntimeException("Can't update database: Mongo updater provider not found");
-            }
+            logger.trace("Don't have DBLock retrieved before upgrade. Needs to acquire lock first in separate transaction");
 
-            DBLockProvider dbLock = new DBLockManager(session).getDBLock();
-            if (dbLock.hasLock()) {
-                updateOrValidateDB(databaseSchema, session, mongoUpdater);
-            } else {
-                logger.trace("Don't have DBLock retrieved before upgrade. Needs to acquire lock first in separate transaction");
-
-                KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
-
-                    @Override
-                    public void run(KeycloakSession lockSession) {
-                        DBLockManager dbLockManager = new DBLockManager(lockSession);
-                        DBLockProvider dbLock2 = dbLockManager.getDBLock();
-                        dbLock2.waitForLock();
-                        try {
-                            updateOrValidateDB(databaseSchema, session, mongoUpdater);
-                        } finally {
-                            dbLock2.releaseLock();
-                        }
-                    }
+            KeycloakModelUtils.runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
 
-                });
-            }
+                @Override
+                public void run(KeycloakSession lockSession) {
+                    DBLockManager dbLockManager = new DBLockManager(lockSession);
+                    DBLockProvider dbLock2 = dbLockManager.getDBLock();
+                    dbLock2.waitForLock();
+                    try {
+                        updateOrValidateDB(strategy, session, mongoUpdater);
+                    } finally {
+                        dbLock2.releaseLock();
+                    }
+                }
 
-            if (databaseSchema.equals("update")) {
-                mongoUpdater.update(session, db);
-            } else if (databaseSchema.equals("validate")) {
-                mongoUpdater.validate(session, db);
-            } else {
-                throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
-            }
+            });
         }
     }
 
@@ -217,13 +209,14 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
         return entityClasses;
     }
 
-    protected void updateOrValidateDB(String databaseSchema, KeycloakSession session, MongoUpdaterProvider mongoUpdater) {
-        if (databaseSchema.equals("update")) {
-            mongoUpdater.update(session, db);
-        } else if (databaseSchema.equals("validate")) {
-            mongoUpdater.validate(session, db);
-        } else {
-            throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
+    protected void updateOrValidateDB(MigrationStrategy strategy, KeycloakSession session, MongoUpdaterProvider mongoUpdater) {
+        switch (strategy) {
+            case UPDATE:
+                mongoUpdater.update(session, db);
+                break;
+            case VALIDATE:
+                mongoUpdater.validate(session, db);
+                break;
         }
     }
 
@@ -345,4 +338,18 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
   		return operationalInfo;
   	}
 
+    private MigrationStrategy getMigrationStrategy() {
+        String migrationStrategy = config.get("migrationStrategy");
+        if (migrationStrategy == null) {
+            // Support 'databaseSchema' for backwards compatibility
+            migrationStrategy = config.get("databaseSchema");
+        }
+
+        if (migrationStrategy != null) {
+            return MigrationStrategy.valueOf(migrationStrategy.toUpperCase());
+        } else {
+            return MigrationStrategy.UPDATE;
+        }
+    }
+
 }
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
index f4983f9..5d6e053 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ClientAdapter.java
@@ -17,8 +17,6 @@
 
 package org.keycloak.models.mongo.keycloak.adapters;
 
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
 import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientTemplateModel;
@@ -65,6 +63,19 @@ public class ClientAdapter extends AbstractMongoAdapter<MongoClientEntity> imple
     @Override
     public void updateClient() {
         updateMongoEntity();
+
+        session.getKeycloakSessionFactory().publish(new RealmModel.ClientUpdatedEvent() {
+
+            @Override
+            public ClientModel getUpdatedClient() {
+                return ClientAdapter.this;
+            }
+
+            @Override
+            public KeycloakSession getKeycloakSession() {
+                return session;
+            }
+        });
     }
 
 

README.md 1(+1 -0)

diff --git a/README.md b/README.md
index c52a172..14addf7 100755
--- a/README.md
+++ b/README.md
@@ -65,6 +65,7 @@ Contributing
     * [Testsuite](misc/Testsuite.md) - Details about testsuite, but also how to quickly run Keycloak during development and a few test tools (OTP generation, LDAP server, Mail server)
     * [Database Testing](misc/DatabaseTesting.md) - How to do testing of Keycloak on different databases
     * [Updating Database](misc/UpdatingDatabaseSchema.md) - How to change the Keycloak database
+    * [Changing the Default keycloak-subsystem Configuration](misc/UpdatingServerConfig.md) - How to update the default keycloak-subsystem config
 * [Developer Mailing List](https://lists.jboss.org/mailman/listinfo/keycloak-dev) - Mailing list to discuss development of Keycloak
 
 
diff --git a/server-spi/src/main/java/org/keycloak/authorization/store/PolicyStore.java b/server-spi/src/main/java/org/keycloak/authorization/store/PolicyStore.java
index f55db99..51c7dd7 100644
--- a/server-spi/src/main/java/org/keycloak/authorization/store/PolicyStore.java
+++ b/server-spi/src/main/java/org/keycloak/authorization/store/PolicyStore.java
@@ -19,11 +19,10 @@ package org.keycloak.authorization.store;
 
 
 import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
-import org.keycloak.authorization.model.Scope;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * A {@link PolicyStore} is responsible to manage the persistence of {@link Policy} instances.
@@ -76,6 +75,15 @@ public interface PolicyStore {
     List<Policy> findByResourceServer(String resourceServerId);
 
     /**
+     * Returns a list of {@link Policy} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
+     *
+     * @param attributes a map holding the attributes that will be used as a filter
+     * @param resourceServerId the identifier of a resource server
+     * @return a list of policies that belong to the given resource server
+     */
+    List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
+
+    /**
      * Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Resource} with the given <code>resourceId</code>.
      *
      * @param resourceId the identifier of a resource
diff --git a/server-spi/src/main/java/org/keycloak/authorization/store/ResourceStore.java b/server-spi/src/main/java/org/keycloak/authorization/store/ResourceStore.java
index 5b92808..f06be78 100644
--- a/server-spi/src/main/java/org/keycloak/authorization/store/ResourceStore.java
+++ b/server-spi/src/main/java/org/keycloak/authorization/store/ResourceStore.java
@@ -19,10 +19,9 @@ package org.keycloak.authorization.store;
 
 import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
-import org.keycloak.authorization.model.Scope;
 
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 /**
  * A {@link ResourceStore} is responsible to manage the persistence of {@link Resource} instances.
@@ -73,6 +72,15 @@ public interface ResourceStore {
     List<Resource> findByResourceServer(String resourceServerId);
 
     /**
+     * Finds all {@link Resource} instances associated with a given resource server.
+     *
+     * @param attributes a map holding the attributes that will be used as a filter
+     * @param resourceServerId the identifier of the resource server
+     * @return a list with all resources associated with the given resource server
+     */
+    List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
+
+    /**
      * Finds all {@link Resource} associated with a given scope.
      *
      * @param id one or more scope identifiers
diff --git a/server-spi/src/main/java/org/keycloak/authorization/store/ScopeStore.java b/server-spi/src/main/java/org/keycloak/authorization/store/ScopeStore.java
index 501217f..81a7064 100644
--- a/server-spi/src/main/java/org/keycloak/authorization/store/ScopeStore.java
+++ b/server-spi/src/main/java/org/keycloak/authorization/store/ScopeStore.java
@@ -22,6 +22,7 @@ import org.keycloak.authorization.model.ResourceServer;
 import org.keycloak.authorization.model.Scope;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * A {@link ScopeStore} is responsible to manage the persistence of {@link Scope} instances.
@@ -75,4 +76,14 @@ public interface ScopeStore {
      * @return a list of scopes that belong to the given resource server
      */
     List<Scope> findByResourceServer(String id);
-}
+
+    /**
+     * Returns a list of {@link Scope} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
+     *
+     * @param attributes a map holding the attributes that will be used as a filter
+     * @param resourceServerId the identifier of a resource server
+     *
+     * @return a list of scopes that belong to the given resource server
+     */
+    List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
+}
\ No newline at end of file
diff --git a/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderFactory.java b/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderFactory.java
index e8be6d6..953797b 100755
--- a/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderFactory.java
+++ b/server-spi/src/main/java/org/keycloak/broker/provider/AbstractIdentityProviderFactory.java
@@ -50,7 +50,7 @@ public abstract class AbstractIdentityProviderFactory<T extends IdentityProvider
     }
 
     @Override
-    public Map<String, String> parseConfig(InputStream inputStream) {
+    public Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream) {
         return new HashMap<String, String>();
     }
 }
diff --git a/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java b/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java
index fba8e64..93ef720 100755
--- a/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java
+++ b/server-spi/src/main/java/org/keycloak/broker/provider/IdentityProviderFactory.java
@@ -17,6 +17,7 @@
 package org.keycloak.broker.provider;
 
 import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.provider.ProviderFactory;
 
 import java.io.InputStream;
@@ -47,8 +48,9 @@ public interface IdentityProviderFactory<T extends IdentityProvider> extends Pro
      * <p>Creates an {@link IdentityProvider} based on the configuration from
      * <code>inputStream</code>.</p>
      *
+     * @param session
      * @param inputStream The input stream from where configuration will be loaded from..
      * @return
      */
-    Map<String, String> parseConfig(InputStream inputStream);
+    Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream);
 }
\ No newline at end of file
diff --git a/server-spi/src/main/java/org/keycloak/events/Details.java b/server-spi/src/main/java/org/keycloak/events/Details.java
index e5da713..772eaa7 100755
--- a/server-spi/src/main/java/org/keycloak/events/Details.java
+++ b/server-spi/src/main/java/org/keycloak/events/Details.java
@@ -58,4 +58,7 @@ public interface Details {
 
     String CLIENT_AUTH_METHOD = "client_auth_method";
 
+    String SIGNATURE_REQUIRED = "signature_required";
+    String SIGNATURE_ALGORITHM = "signature_algorithm";
+
 }
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java
index 08da081..2afbbcc 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java
@@ -49,8 +49,8 @@ public class MigrationUtils {
 
     public static void updateOTPRequiredAction(RequiredActionProviderModel otpAction) {
         if (otpAction == null) return;
-        if (!otpAction.getProviderId().equals(UserModel.RequiredAction.CONFIGURE_TOTP.name())) return;
-        if (!otpAction.getName().equals("Configure Totp")) return;
+        if (!UserModel.RequiredAction.CONFIGURE_TOTP.name().equals(otpAction.getProviderId())) return;
+        if (!"Configure Totp".equals(otpAction.getName())) return;
 
         otpAction.setName("Configure OTP");
     }
diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java
index 04f1476..61dc9c1 100755
--- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java
@@ -56,6 +56,12 @@ public interface RealmModel extends RoleContainerModel {
         ClientModel getCreatedClient();
     }
 
+    // Called also during client creation after client is fully initialized (including all attributes etc)
+    interface ClientUpdatedEvent extends ProviderEvent {
+        ClientModel getUpdatedClient();
+        KeycloakSession getKeycloakSession();
+    }
+
     interface ClientRemovedEvent extends ProviderEvent {
         ClientModel getClient();
         KeycloakSession getKeycloakSession();
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index f36f010..d1d5b05 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -943,7 +943,6 @@ public class RepresentationToModel {
         } else {
             client.setNodeReRegistrationTimeout(-1);
         }
-        client.updateClient();
 
         if (resourceRep.getNotBefore() != null) {
             client.setNotBefore(resourceRep.getNotBefore());
@@ -1043,6 +1042,8 @@ public class RepresentationToModel {
         if (resourceRep.isUseTemplateMappers() != null) client.setUseTemplateMappers(resourceRep.isUseTemplateMappers());
         else client.setUseTemplateMappers(resourceRep.getClientTemplate() != null);
 
+        client.updateClient();
+
         return client;
     }
 
@@ -1066,7 +1067,6 @@ public class RepresentationToModel {
         if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
         if (rep.getNodeReRegistrationTimeout() != null) resource.setNodeReRegistrationTimeout(rep.getNodeReRegistrationTimeout());
         if (rep.getClientAuthenticatorType() != null) resource.setClientAuthenticatorType(rep.getClientAuthenticatorType());
-        resource.updateClient();
 
         if (rep.getProtocol() != null) resource.setProtocol(rep.getProtocol());
         if (rep.getAttributes() != null) {
@@ -1122,7 +1122,7 @@ public class RepresentationToModel {
             }
         }
 
-
+        resource.updateClient();
     }
 
     // CLIENT TEMPLATES
diff --git a/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapper.java b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapper.java
index 1942422..8055fae 100755
--- a/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapper.java
+++ b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapper.java
@@ -17,6 +17,10 @@
 
 package org.keycloak.protocol;
 
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperContainerModel;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
 import org.keycloak.provider.ConfiguredProvider;
 import org.keycloak.provider.Provider;
 import org.keycloak.provider.ProviderFactory;
@@ -30,4 +34,16 @@ public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper
     String getDisplayCategory();
     String getDisplayType();
 
+    /**
+     * Called when instance of mapperModel is created/updated for this protocolMapper through admin endpoint
+     *
+     * @param session
+     * @param realm
+     * @param client client or clientTemplate
+     * @param mapperModel
+     * @throws ProtocolMapperConfigException if configuration provided in mapperModel is not valid
+     */
+    default void validateConfig(KeycloakSession session, RealmModel realm, ProtocolMapperContainerModel client, ProtocolMapperModel mapperModel) throws ProtocolMapperConfigException {
+    };
+
 }
diff --git a/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java
new file mode 100644
index 0000000..f50a73d
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/protocol/ProtocolMapperConfigException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ProtocolMapperConfigException extends Exception {
+
+    private Object[] parameters;
+
+    public ProtocolMapperConfigException(String message) {
+        super(message);
+    }
+
+    public ProtocolMapperConfigException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ProtocolMapperConfigException(String message, Object ... parameters) {
+        super(message);
+        this.parameters = parameters;
+    }
+
+    public Object[] getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Object[] parameters) {
+        this.parameters = parameters;
+    }
+
+}
diff --git a/server-spi/src/main/java/org/keycloak/ServerStartupError.java b/server-spi/src/main/java/org/keycloak/ServerStartupError.java
new file mode 100644
index 0000000..967e66f
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/ServerStartupError.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak;
+
+/**
+ * Non-recoverable error thrown during server startup
+ *
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ServerStartupError extends Error {
+
+    private final boolean fillStackTrace;
+
+    public ServerStartupError(String message) {
+        super(message);
+        fillStackTrace = true;
+    }
+
+    public ServerStartupError(String message, boolean fillStackTrace) {
+        super(message);
+        this.fillStackTrace = fillStackTrace;
+    }
+
+    @Override
+    public synchronized Throwable fillInStackTrace() {
+        if (fillStackTrace) {
+            return super.fillInStackTrace();
+        } else {
+            return this;
+        }
+    }
+
+}

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

diff --git a/services/pom.xml b/services/pom.xml
index a8a009d..57d7984 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -73,6 +73,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.wildfly.core</groupId>
+            <artifactId>wildfly-controller</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.jboss.logging</groupId>
             <artifactId>jboss-logging</artifactId>
         </dependency>
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
index 620e0c9..e56e7e6 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/broker/IdpEmailVerificationAuthenticator.java
@@ -132,6 +132,9 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator 
                     clientSession.setNote(IS_DIFFERENT_BROWSER, "true");
                 }
 
+                // User successfully confirmed linking by email verification. His email was defacto verified
+                existingUser.setEmailVerified(true);
+
                 context.setUser(existingUser);
                 context.success();
             } else {
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
index 5139e3a..86dd4e8 100644
--- a/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/client/JWTClientAuthenticator.java
@@ -30,6 +30,7 @@ import java.util.Set;
 
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
 
 import org.keycloak.OAuth2Constants;
 import org.keycloak.authentication.AuthenticationFlowError;
@@ -39,9 +40,11 @@ import org.keycloak.jose.jws.JWSInput;
 import org.keycloak.jose.jws.crypto.RSAProvider;
 import org.keycloak.models.AuthenticationExecutionModel;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ModelException;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.JsonWebToken;
 import org.keycloak.representations.idm.CertificateRepresentation;
@@ -139,10 +142,11 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
                 throw new RuntimeException("Signature on JWT token failed validation");
             }
 
-            // Validate other things
-            String expectedAudience = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
-            if (!token.hasAudience(expectedAudience)) {
-                throw new RuntimeException("Token audience doesn't match domain. Realm audience is '" + expectedAudience + "' but audience from token is '" + Arrays.asList(token.getAudience()).toString() + "'");
+            // Allow both "issuer" or "token-endpoint" as audience
+            String issuerUrl = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
+            String tokenUrl = OIDCLoginProtocolService.tokenUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
+            if (!token.hasAudience(issuerUrl) && !token.hasAudience(tokenUrl)) {
+                throw new RuntimeException("Token audience doesn't match domain. Realm issuer is '" + issuerUrl + "' but audience from token is '" + Arrays.asList(token.getAudience()).toString() + "'");
             }
 
             if (!token.isActive()) {
@@ -163,30 +167,13 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
     }
 
     protected PublicKey getSignatureValidationKey(ClientModel client, ClientAuthenticationFlowContext context) {
-        CertificateRepresentation certInfo = CertificateInfoHelper.getCertificateFromClient(client, ATTR_PREFIX);
-
-        String encodedCertificate = certInfo.getCertificate();
-        String encodedPublicKey = certInfo.getPublicKey();
-
-        if (encodedCertificate == null && encodedPublicKey == null) {
-            Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client '" + client.getClientId() + "' doesn't have certificate or publicKey configured");
-            context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
-            return null;
-        }
-
-        if (encodedCertificate != null && encodedPublicKey != null) {
-            Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client '" + client.getClientId() + "' has both publicKey and certificate configured");
+        try {
+            return CertificateInfoHelper.getSignatureValidationKey(client, ATTR_PREFIX);
+        } catch (ModelException me) {
+            Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", me.getMessage());
             context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
             return null;
         }
-
-        // TODO: Caching of publicKeys / certificates, so it doesn't need to be always computed from pem. For performance reasons...
-        if (encodedCertificate != null) {
-            X509Certificate clientCert = KeycloakModelUtils.getCertificate(encodedCertificate);
-            return clientCert.getPublicKey();
-        } else {
-            return KeycloakModelUtils.getPublicKey(encodedPublicKey);
-        }
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
index d7e6dee..3b9c194 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/PolicyService.java
@@ -26,8 +26,10 @@ import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
 import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.StoreFactory;
+import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyProviderRepresentation;
 import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.services.resources.admin.RealmAuth;
 
 import javax.ws.rs.Consumes;
@@ -41,6 +43,12 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
@@ -188,11 +196,54 @@ public class PolicyService {
     @GET
     @Produces("application/json")
     @NoCache
-    public Response findAll() {
+    public Response findAll(@QueryParam("name") String name,
+                            @QueryParam("type") String type,
+                            @QueryParam("resource") String resource,
+                            @QueryParam("permission") Boolean permission,
+                            @QueryParam("first") Integer firstResult,
+                            @QueryParam("max") Integer maxResult) {
         this.auth.requireView();
+
+        Map<String, String[]> search = new HashMap<>();
+
+        if (name != null && !"".equals(name.trim())) {
+            search.put("name", new String[] {name});
+        }
+
+        if (type != null && !"".equals(type.trim())) {
+            search.put("type", new String[] {type});
+        }
+
         StoreFactory storeFactory = authorization.getStoreFactory();
+
+        if (resource != null && !"".equals(resource.trim())) {
+            List<Policy> policies = new ArrayList<>();
+            HashMap<String, String[]> resourceSearch = new HashMap<>();
+
+            resourceSearch.put("name", new String[] {resource});
+
+            storeFactory.getResourceStore().findByResourceServer(resourceSearch, resourceServer.getId(), -1, -1).forEach(resource1 -> {
+                ResourceRepresentation resourceRepresentation = ModelToRepresentation.toRepresentation(resource1, resourceServer, authorization);
+                resourceRepresentation.getPolicies().forEach(policyRepresentation -> {
+                    Policy associated = storeFactory.getPolicyStore().findById(policyRepresentation.getId());
+                    policies.add(associated);
+                    findAssociatedPolicies(associated, policies);
+                });
+            });
+
+            if (policies.isEmpty()) {
+                return Response.ok(Collections.emptyList()).build();
+            }
+
+            search.put("id", policies.stream().map(Policy::getId).toArray(String[]::new));
+        }
+
+        if (permission != null) {
+            search.put("permission", new String[] {permission.toString()});
+        }
+
         return Response.ok(
-                storeFactory.getPolicyStore().findByResourceServer(resourceServer.getId()).stream()
+                storeFactory.getPolicyStore().findByResourceServer(search, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : -1).stream()
                         .map(policy -> toRepresentation(policy, authorization))
                         .collect(Collectors.toList()))
                 .build();
@@ -244,4 +295,11 @@ public class PolicyService {
 
         return null;
     }
+
+    private void findAssociatedPolicies(Policy policy, List<Policy> policies) {
+        policy.getAssociatedPolicies().forEach(associated -> {
+            policies.add(associated);
+            findAssociatedPolicies(associated, policies);
+        });
+    }
 }
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
index c628a82..d31146f 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ResourceSetService.java
@@ -22,9 +22,13 @@ import org.keycloak.authorization.AuthorizationProvider;
 import org.keycloak.authorization.model.Policy;
 import org.keycloak.authorization.model.Resource;
 import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Scope;
 import org.keycloak.authorization.store.PolicyStore;
 import org.keycloak.authorization.store.ResourceStore;
 import org.keycloak.authorization.store.StoreFactory;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.authorization.ResourceRepresentation;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.services.resources.admin.RealmAuth;
@@ -40,7 +44,10 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
@@ -170,12 +177,63 @@ public class ResourceSetService {
     @GET
     @NoCache
     @Produces("application/json")
-    public Response findAll() {
+    public Response findAll(@QueryParam("name") String name,
+                            @QueryParam("uri") String uri,
+                            @QueryParam("owner") String owner,
+                            @QueryParam("type") String type,
+                            @QueryParam("scope") String scope,
+                            @QueryParam("first") Integer firstResult,
+                            @QueryParam("max") Integer maxResult) {
         requireView();
         StoreFactory storeFactory = authorization.getStoreFactory();
 
+        Map<String, String[]> search = new HashMap<>();
+
+        if (name != null && !"".equals(name.trim())) {
+            search.put("name", new String[] {name});
+        }
+
+        if (uri != null && !"".equals(uri.trim())) {
+            search.put("uri", new String[] {uri});
+        }
+
+        if (owner != null && !"".equals(owner.trim())) {
+            RealmModel realm = authorization.getKeycloakSession().getContext().getRealm();
+            ClientModel clientModel = realm.getClientByClientId(owner);
+
+            if (clientModel != null) {
+                owner = clientModel.getId();
+            } else {
+                UserModel user = authorization.getKeycloakSession().users().getUserByUsername(owner, realm);
+
+                if (user != null) {
+                    owner = user.getId();
+                }
+            }
+
+            search.put("owner", new String[] {owner});
+        }
+
+        if (type != null && !"".equals(type.trim())) {
+            search.put("type", new String[] {type});
+        }
+
+        if (scope != null && !"".equals(scope.trim())) {
+            HashMap<String, String[]> scopeFilter = new HashMap<>();
+
+            scopeFilter.put("name", new String[] {scope});
+
+            List<Scope> scopes = authorization.getStoreFactory().getScopeStore().findByResourceServer(scopeFilter, resourceServer.getId(), -1, -1);
+
+            if (scopes.isEmpty()) {
+                return Response.ok(Collections.emptyList()).build();
+            }
+
+            search.put("scope", scopes.stream().map(Scope::getId).toArray(String[]::new));
+        }
+
         return Response.ok(
-                storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream()
+                storeFactory.getResourceStore().findByResourceServer(search, this.resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : -1).stream()
                         .map(resource -> toRepresentation(resource, this.resourceServer, authorization))
                         .collect(Collectors.toList()))
                 .build();
diff --git a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
index df0e6da..44464b4 100644
--- a/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
+++ b/services/src/main/java/org/keycloak/authorization/admin/ScopeService.java
@@ -41,7 +41,9 @@ import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
@@ -158,10 +160,19 @@ public class ScopeService {
 
     @GET
     @Produces("application/json")
-    public Response findAll() {
+    public Response findAll(@QueryParam("name") String name,
+                            @QueryParam("first") Integer firstResult,
+                            @QueryParam("max") Integer maxResult) {
         this.auth.requireView();
+
+        Map<String, String[]> search = new HashMap<>();
+
+        if (name != null && !"".equals(name.trim())) {
+            search.put("name", new String[] {name});
+        }
+
         return Response.ok(
-                this.authorization.getStoreFactory().getScopeStore().findByResourceServer(this.resourceServer.getId()).stream()
+                this.authorization.getStoreFactory().getScopeStore().findByResourceServer(search, this.resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : -1).stream()
                         .map(scope -> toRepresentation(scope, this.authorization))
                         .collect(Collectors.toList()))
                 .build();
diff --git a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
index 168d62b..b02a935 100644
--- a/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
+++ b/services/src/main/java/org/keycloak/authorization/protection/resource/ResourceService.java
@@ -109,7 +109,7 @@ public class ResourceService {
     }
 
     private Set<String> findAll() {
-        Response response = this.resourceManager.findAll();
+        Response response = this.resourceManager.findAll(null, null, null, null, null, -1, -1);
         List<ResourceRepresentation> resources = (List<ResourceRepresentation>) response.getEntity();
         return resources.stream().map(ResourceRepresentation::getId).collect(Collectors.toSet());
     }
diff --git a/services/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProviderFactory.java b/services/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProviderFactory.java
index d3e8eba..56f24a2 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProviderFactory.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/KeycloakOIDCIdentityProviderFactory.java
@@ -18,6 +18,7 @@ package org.keycloak.broker.oidc;
 
 import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
 import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
 
 import java.io.InputStream;
 import java.util.Map;
@@ -45,8 +46,8 @@ public class KeycloakOIDCIdentityProviderFactory extends AbstractIdentityProvide
     }
 
     @Override
-    public Map<String, String> parseConfig(InputStream inputStream) {
-        return OIDCIdentityProviderFactory.parseOIDCConfig(inputStream);
+    public Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream) {
+        return OIDCIdentityProviderFactory.parseOIDCConfig(session, inputStream);
 
     }
 
diff --git a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java
index 82c2cdd..a0e5017 100755
--- a/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java
+++ b/services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProviderFactory.java
@@ -19,6 +19,7 @@ package org.keycloak.broker.oidc;
 import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
 import org.keycloak.jose.jwk.JWK;
 import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.jose.jwk.JSONWebKeySet;
 import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
@@ -56,11 +57,11 @@ public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory
     }
 
     @Override
-    public Map<String, String> parseConfig(InputStream inputStream) {
-        return parseOIDCConfig(inputStream);
+    public Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream) {
+        return parseOIDCConfig(session, inputStream);
     }
 
-    protected static Map<String, String> parseOIDCConfig(InputStream inputStream) {
+    protected static Map<String, String> parseOIDCConfig(KeycloakSession session, InputStream inputStream) {
         OIDCConfigurationRepresentation rep;
         try {
             rep = JsonSerialization.readValue(inputStream, OIDCConfigurationRepresentation.class);
@@ -74,14 +75,14 @@ public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory
         config.setTokenUrl(rep.getTokenEndpoint());
         config.setUserInfoUrl(rep.getUserinfoEndpoint());
         if (rep.getJwksUri() != null) {
-            sendJwksRequest(rep, config);
+            sendJwksRequest(session, rep, config);
         }
         return config.getConfig();
     }
 
-    protected static void sendJwksRequest(OIDCConfigurationRepresentation rep, OIDCIdentityProviderConfig config) {
+    protected static void sendJwksRequest(KeycloakSession session, OIDCConfigurationRepresentation rep, OIDCIdentityProviderConfig config) {
         try {
-            JSONWebKeySet keySet = JWKSUtils.sendJwksRequest(rep.getJwksUri());
+            JSONWebKeySet keySet = JWKSUtils.sendJwksRequest(session, rep.getJwksUri());
             PublicKey key = JWKSUtils.getKeyForUse(keySet, JWK.Use.SIG);
             if (key == null) {
                 logger.supportedJwkNotFound(JWK.Use.SIG.asString());
diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
index dac6750..2617995 100755
--- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
+++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java
@@ -24,6 +24,7 @@ import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
 import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
 import org.keycloak.dom.saml.v2.metadata.KeyTypes;
 import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
 import org.keycloak.saml.common.exceptions.ParsingException;
 import org.keycloak.saml.common.util.DocumentUtil;
@@ -54,7 +55,7 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
     }
 
     @Override
-    public Map<String, String> parseConfig(InputStream inputStream) {
+    public Map<String, String> parseConfig(KeycloakSession session, InputStream inputStream) {
         try {
             Object parsedObject = new SAMLParser().parse(inputStream);
             EntityDescriptorType entityType;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 931b04c..1b4db29 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -17,11 +17,6 @@
 
 package org.keycloak.protocol.oidc.endpoints;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
 import javax.ws.rs.GET;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
@@ -42,6 +37,8 @@ import org.keycloak.models.IdentityProviderModel;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.AuthorizationEndpointBase;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.endpoints.request.AuthorizationEndpointRequest;
+import org.keycloak.protocol.oidc.endpoints.request.AuthorizationEndpointRequestParserProcessor;
 import org.keycloak.protocol.oidc.utils.OIDCRedirectUriBuilder;
 import org.keycloak.protocol.oidc.utils.OIDCResponseMode;
 import org.keycloak.protocol.oidc.utils.OIDCResponseType;
@@ -67,43 +64,10 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
     /**
      * Prefix used to store additional HTTP GET params from original client request into {@link ClientSessionModel} note to be available later in Authenticators, RequiredActions etc. Prefix is used to
      * prevent collisions with internally used notes.
-     * 
+     *
      * @see ClientSessionModel#getNote(String)
-     * @see #KNOWN_REQ_PARAMS
-     * @see #additionalReqParams
      */
     public static final String CLIENT_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX = "client_request_param_";
-    /**
-     * Max number of additional req params copied into client session note to prevent DoS attacks
-     * 
-     * @see #additionalReqParams
-     */
-    public static final int ADDITIONAL_REQ_PARAMS_MAX_MUMBER = 5;
-    /**
-     * Max size of additional req param value copied into client session note to prevent DoS attacks - params with longer value are ignored
-     * 
-     * @see #additionalReqParams
-     */
-    public static final int ADDITIONAL_REQ_PARAMS_MAX_SIZE = 200;
-
-    /** Set of known protocol GET params not to be stored into {@link #additionalReqParams} */
-    private static final Set<String> KNOWN_REQ_PARAMS = new HashSet<>();
-    static {
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.CLIENT_ID_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.REDIRECT_URI_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.STATE_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.SCOPE_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.LOGIN_HINT_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.PROMPT_PARAM);
-        KNOWN_REQ_PARAMS.add(AdapterConstants.KC_IDP_HINT);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.NONCE_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.MAX_AGE_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.UI_LOCALES_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.REQUEST_PARAM);
-        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.REQUEST_URI_PARAM);
-    }
 
     private enum Action {
         REGISTER, CODE, FORGOT_CREDENTIALS
@@ -116,19 +80,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
     private OIDCResponseType parsedResponseType;
     private OIDCResponseMode parsedResponseMode;
 
-    private String clientId;
+    private AuthorizationEndpointRequest request;
     private String redirectUri;
-    private String redirectUriParam;
-    private String responseType;
-    private String responseMode;
-    private String state;
-    private String scope;
-    private String loginHint;
-    private String prompt;
-    private String nonce;
-    private String maxAge;
-    private String idpHint;
-    protected Map<String, String> additionalReqParams = new HashMap<>();
 
     public AuthorizationEndpoint(RealmModel realm, EventBuilder event) {
         super(realm, event);
@@ -139,34 +92,25 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
     public Response build() {
         MultivaluedMap<String, String> params = uriInfo.getQueryParameters();
 
-        clientId = params.getFirst(OIDCLoginProtocol.CLIENT_ID_PARAM);
-        responseType = params.getFirst(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
-        responseMode = params.getFirst(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
-        redirectUriParam = params.getFirst(OIDCLoginProtocol.REDIRECT_URI_PARAM);
-        state = params.getFirst(OIDCLoginProtocol.STATE_PARAM);
-        scope = params.getFirst(OIDCLoginProtocol.SCOPE_PARAM);
-        loginHint = params.getFirst(OIDCLoginProtocol.LOGIN_HINT_PARAM);
-        prompt = params.getFirst(OIDCLoginProtocol.PROMPT_PARAM);
-        idpHint = params.getFirst(AdapterConstants.KC_IDP_HINT);
-        nonce = params.getFirst(OIDCLoginProtocol.NONCE_PARAM);
-        maxAge = params.getFirst(OIDCLoginProtocol.MAX_AGE_PARAM);
-
-        extractAdditionalReqParams(params);
+        String clientId = params.getFirst(OIDCLoginProtocol.CLIENT_ID_PARAM);
 
         checkSsl();
         checkRealm();
-        checkClient();
+        checkClient(clientId);
+
+        request = AuthorizationEndpointRequestParserProcessor.parseRequest(event, session, client, params);
+
         checkRedirectUri();
         Response errorResponse = checkResponseType();
         if (errorResponse != null) {
             return errorResponse;
         }
 
-        if (!TokenUtil.isOIDCRequest(scope)) {
+        if (!TokenUtil.isOIDCRequest(request.getScope())) {
             logger.oidcScopeMissing();
         }
 
-        errorResponse = checkOIDCParams(params);
+        errorResponse = checkOIDCParams();
         if (errorResponse != null) {
             return errorResponse;
         }
@@ -186,27 +130,6 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         throw new RuntimeException("Unknown action " + action);
     }
 
-    protected void extractAdditionalReqParams(MultivaluedMap<String, String> params) {
-        for (String paramName : params.keySet()) {
-            if (!KNOWN_REQ_PARAMS.contains(paramName)) {
-                String value = params.getFirst(paramName);
-                if (value != null && value.trim().isEmpty()) {
-                    value = null;
-                }
-                if (value != null && value.length() <= ADDITIONAL_REQ_PARAMS_MAX_SIZE) {
-                    if (additionalReqParams.size() >= ADDITIONAL_REQ_PARAMS_MAX_MUMBER) {
-                        logger.debug("Maximal number of additional OIDC params (" + ADDITIONAL_REQ_PARAMS_MAX_MUMBER + ") exceeded, ignoring rest of them!");
-                        break;
-                    }
-                    additionalReqParams.put(paramName, value);
-                } else {
-                    logger.debug("OIDC Additional param " + paramName + " ignored because value is empty or longer than " + ADDITIONAL_REQ_PARAMS_MAX_SIZE);
-                }
-            }
-
-        }
-    }
-
     public AuthorizationEndpoint register() {
         event.event(EventType.REGISTER);
         action = Action.REGISTER;
@@ -243,7 +166,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         }
     }
 
-    private void checkClient() {
+    private void checkClient(String clientId) {
         if (clientId == null) {
             event.error(Errors.INVALID_REQUEST);
             throw new ErrorPageException(session, Messages.MISSING_PARAMETER, OIDCLoginProtocol.CLIENT_ID_PARAM);
@@ -271,6 +194,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
     }
 
     private Response checkResponseType() {
+        String responseType = request.getResponseType();
+
         if (responseType == null) {
             logger.missingParameter(OAuth2Constants.RESPONSE_TYPE);
             event.error(Errors.INVALID_REQUEST);
@@ -292,7 +217,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
 
         OIDCResponseMode parsedResponseMode = null;
         try {
-            parsedResponseMode = OIDCResponseMode.parse(responseMode, parsedResponseType);
+            parsedResponseMode = OIDCResponseMode.parse(request.getResponseMode(), parsedResponseType);
         } catch (IllegalArgumentException iae) {
             logger.invalidParameter(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
             event.error(Errors.INVALID_REQUEST);
@@ -325,20 +250,8 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         return null;
     }
 
-    private Response checkOIDCParams(MultivaluedMap<String, String> params) {
-        if (params.getFirst(OIDCLoginProtocol.REQUEST_PARAM) != null) {
-            logger.unsupportedParameter(OIDCLoginProtocol.REQUEST_PARAM);
-            event.error(Errors.INVALID_REQUEST);
-            return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_NOT_SUPPORTED, null);
-        }
-
-        if (params.getFirst(OIDCLoginProtocol.REQUEST_URI_PARAM) != null) {
-            logger.unsupportedParameter(OIDCLoginProtocol.REQUEST_URI_PARAM);
-            event.error(Errors.INVALID_REQUEST);
-            return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, null);
-        }
-
-        if (parsedResponseType.isImplicitOrHybridFlow() && nonce == null) {
+    private Response checkOIDCParams() {
+        if (parsedResponseType.isImplicitOrHybridFlow() && request.getNonce() == null) {
             logger.missingParameter(OIDCLoginProtocol.NONCE_PARAM);
             event.error(Errors.INVALID_REQUEST);
             return redirectErrorToClient(parsedResponseMode, OAuthErrorException.INVALID_REQUEST, "Missing parameter: nonce");
@@ -355,14 +268,16 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
             errorResponseBuilder.addParam(OAuth2Constants.ERROR_DESCRIPTION, errorDescription);
         }
 
-        if (state != null) {
-            errorResponseBuilder.addParam(OAuth2Constants.STATE, state);
+        if (request.getState() != null) {
+            errorResponseBuilder.addParam(OAuth2Constants.STATE, request.getState());
         }
 
         return errorResponseBuilder.build();
     }
 
     private void checkRedirectUri() {
+        String redirectUriParam = request.getRedirectUriParam();
+
         event.detail(Details.REDIRECT_URI, redirectUriParam);
 
         redirectUri = RedirectUtils.verifyRedirectUri(uriInfo, redirectUriParam, realm, client);
@@ -377,27 +292,28 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL);
         clientSession.setRedirectUri(redirectUri);
         clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name());
-        clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, responseType);
-        clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUriParam);
+        clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, request.getResponseType());
+        clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, request.getRedirectUriParam());
         clientSession.setNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
 
-        if (state != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, state);
-        if (nonce != null) clientSession.setNote(OIDCLoginProtocol.NONCE_PARAM, nonce);
-        if (maxAge != null) clientSession.setNote(OIDCLoginProtocol.MAX_AGE_PARAM, maxAge);
-        if (scope != null) clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
-        if (loginHint != null) clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
-        if (prompt != null) clientSession.setNote(OIDCLoginProtocol.PROMPT_PARAM, prompt);
-        if (idpHint != null) clientSession.setNote(AdapterConstants.KC_IDP_HINT, idpHint);
-        if (responseMode != null) clientSession.setNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM, responseMode);
-
-        if (additionalReqParams != null) {
-            for (String paramName : additionalReqParams.keySet()) {
-                clientSession.setNote(CLIENT_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + paramName, additionalReqParams.get(paramName));
+        if (request.getState() != null) clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, request.getState());
+        if (request.getNonce() != null) clientSession.setNote(OIDCLoginProtocol.NONCE_PARAM, request.getNonce());
+        if (request.getMaxAge() != null) clientSession.setNote(OIDCLoginProtocol.MAX_AGE_PARAM, String.valueOf(request.getMaxAge()));
+        if (request.getScope() != null) clientSession.setNote(OIDCLoginProtocol.SCOPE_PARAM, request.getScope());
+        if (request.getLoginHint() != null) clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, request.getLoginHint());
+        if (request.getPrompt() != null) clientSession.setNote(OIDCLoginProtocol.PROMPT_PARAM, request.getPrompt());
+        if (request.getIdpHint() != null) clientSession.setNote(AdapterConstants.KC_IDP_HINT, request.getIdpHint());
+        if (request.getResponseMode() != null) clientSession.setNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM, request.getResponseMode());
+
+        if (request.getAdditionalReqParams() != null) {
+            for (String paramName : request.getAdditionalReqParams().keySet()) {
+                clientSession.setNote(CLIENT_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + paramName, request.getAdditionalReqParams().get(paramName));
             }
         }
     }
 
     private Response buildAuthorizationCodeAuthorizationResponse() {
+        String idpHint = request.getIdpHint();
 
         if (idpHint != null && !"".equals(idpHint)) {
             IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(idpHint);
@@ -413,7 +329,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
         this.event.event(EventType.LOGIN);
         clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
 
-        return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), TokenUtil.hasPrompt(prompt, OIDCLoginProtocol.PROMPT_VALUE_NONE), false);
+        return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), TokenUtil.hasPrompt(request.getPrompt(), OIDCLoginProtocol.PROMPT_VALUE_NONE), false);
     }
 
     private Response buildRegister() {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequest.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequest.java
new file mode 100644
index 0000000..998a58c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.oidc.endpoints.request;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class AuthorizationEndpointRequest {
+
+    String clientId;
+    String redirectUriParam;
+    String responseType;
+    String responseMode;
+    String state;
+    String scope;
+    String loginHint;
+    String prompt;
+    String nonce;
+    Integer maxAge;
+    String idpHint;
+    Map<String, String> additionalReqParams = new HashMap<>();
+
+    public String getClientId() {
+        return clientId;
+    }
+
+    public String getRedirectUriParam() {
+        return redirectUriParam;
+    }
+
+    public String getResponseType() {
+        return responseType;
+    }
+
+    public String getResponseMode() {
+        return responseMode;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public String getScope() {
+        return scope;
+    }
+
+    public String getLoginHint() {
+        return loginHint;
+    }
+
+    public String getPrompt() {
+        return prompt;
+    }
+
+    public String getNonce() {
+        return nonce;
+    }
+
+    public Integer getMaxAge() {
+        return maxAge;
+    }
+
+    public String getIdpHint() {
+        return idpHint;
+    }
+
+    public Map<String, String> getAdditionalReqParams() {
+        return additionalReqParams;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java
new file mode 100644
index 0000000..8db219c
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthorizationEndpointRequestParserProcessor.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.oidc.endpoints.request;
+
+import java.io.InputStream;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.keycloak.common.util.StreamUtil;
+import org.keycloak.connections.httpclient.HttpClientProvider;
+import org.keycloak.events.Errors;
+import org.keycloak.events.EventBuilder;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.services.ErrorPageException;
+import org.keycloak.services.ServicesLogger;
+import org.keycloak.services.messages.Messages;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class AuthorizationEndpointRequestParserProcessor {
+
+    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+
+    public static AuthorizationEndpointRequest parseRequest(EventBuilder event, KeycloakSession session, ClientModel client, MultivaluedMap<String, String> requestParams) {
+        try {
+            AuthorizationEndpointRequest request = new AuthorizationEndpointRequest();
+
+            new AuthzEndpointQueryStringParser(requestParams).parseRequest(request);
+
+            String requestParam = requestParams.getFirst(OIDCLoginProtocol.REQUEST_PARAM);
+            String requestUriParam = requestParams.getFirst(OIDCLoginProtocol.REQUEST_URI_PARAM);
+
+            if (requestParam != null && requestUriParam != null) {
+                throw new RuntimeException("Illegal to use both 'request' and 'request_uri' parameters together");
+            }
+
+            if (requestParam != null) {
+                new AuthzEndpointRequestObjectParser(requestParam, client).parseRequest(request);
+            } else if (requestUriParam != null) {
+                InputStream is = session.getProvider(HttpClientProvider.class).get(requestUriParam);
+                String retrievedRequest = StreamUtil.readString(is);
+
+                new AuthzEndpointRequestObjectParser(retrievedRequest, client).parseRequest(request);
+            }
+
+            return request;
+
+        } catch (Exception e) {
+            logger.invalidRequest(e);
+            event.error(Errors.INVALID_REQUEST);
+            throw new ErrorPageException(session, Messages.INVALID_REQUEST);
+        }
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointQueryStringParser.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointQueryStringParser.java
new file mode 100644
index 0000000..8384fdc
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointQueryStringParser.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.oidc.endpoints.request;
+
+import java.util.Set;
+
+import javax.ws.rs.core.MultivaluedMap;
+
+/**
+ * Parse the parameters from request queryString
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+class AuthzEndpointQueryStringParser extends AuthzEndpointRequestParser {
+
+    private final MultivaluedMap<String, String> requestParams;
+
+    public AuthzEndpointQueryStringParser(MultivaluedMap<String, String> requestParams) {
+        this.requestParams = requestParams;
+    }
+
+    @Override
+    protected String getParameter(String paramName) {
+        return requestParams.getFirst(paramName);
+    }
+
+    @Override
+    protected Integer getIntParameter(String paramName) {
+        String paramVal = requestParams.getFirst(paramName);
+        return paramVal==null ? null : Integer.parseInt(paramVal);
+    }
+
+    @Override
+    protected Set<String> keySet() {
+        return requestParams.keySet();
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestObjectParser.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestObjectParser.java
new file mode 100644
index 0000000..658a2c0
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestObjectParser.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.oidc.endpoints.request;
+
+import java.security.PublicKey;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.jose.jws.JWSHeader;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.ClientModel;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
+import org.keycloak.services.util.CertificateInfoHelper;
+import org.keycloak.util.JsonSerialization;
+
+/**
+ * Parse the parameters from OIDC "request" object
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+class AuthzEndpointRequestObjectParser extends AuthzEndpointRequestParser {
+
+    private final Map<String, Object> requestParams;
+
+    public AuthzEndpointRequestObjectParser(String requestObject, ClientModel client) throws Exception {
+        JWSInput input = new JWSInput(requestObject);
+        JWSHeader header = input.getHeader();
+
+        Algorithm requestedSignatureAlgorithm = OIDCAdvancedConfigWrapper.fromClientModel(client).getRequestObjectSignatureAlg();
+
+        if (requestedSignatureAlgorithm != null && requestedSignatureAlgorithm != header.getAlgorithm()) {
+            throw new RuntimeException("Request object signed with different algorithm than client requested algorithm");
+        }
+
+        if (header.getAlgorithm() == Algorithm.none) {
+            this.requestParams = JsonSerialization.readValue(input.getContent(), TypedHashMap.class);
+        } else if (header.getAlgorithm() == Algorithm.RS256) {
+            PublicKey clientPublicKey = CertificateInfoHelper.getSignatureValidationKey(client, JWTClientAuthenticator.ATTR_PREFIX);
+            boolean verified = RSAProvider.verify(input, clientPublicKey);
+            if (!verified) {
+                throw new RuntimeException("Failed to verify signature on 'request' object");
+            }
+
+            this.requestParams = JsonSerialization.readValue(input.getContent(), TypedHashMap.class);
+        } else {
+            throw new RuntimeException("Unsupported JWA algorithm used for signed request");
+        }
+    }
+
+    @Override
+    protected String getParameter(String paramName) {
+        Object val = this.requestParams.get(paramName);
+        return val==null ? null : val.toString();
+    }
+
+    @Override
+    protected Integer getIntParameter(String paramName) {
+        Object val = this.requestParams.get(paramName);
+        return val==null ? null : Integer.parseInt(getParameter(paramName));
+    }
+
+    @Override
+    protected Set<String> keySet() {
+        return requestParams.keySet();
+    }
+
+    static class TypedHashMap extends HashMap<String, Object> {
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java
new file mode 100644
index 0000000..e322d4b
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/request/AuthzEndpointRequestParser.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.oidc.endpoints.request;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.keycloak.constants.AdapterConstants;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.services.ServicesLogger;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+abstract class AuthzEndpointRequestParser {
+
+    private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+
+    /**
+     * Max number of additional req params copied into client session note to prevent DoS attacks
+     *
+     */
+    public static final int ADDITIONAL_REQ_PARAMS_MAX_MUMBER = 5;
+
+    /**
+     * Max size of additional req param value copied into client session note to prevent DoS attacks - params with longer value are ignored
+     *
+     */
+    public static final int ADDITIONAL_REQ_PARAMS_MAX_SIZE = 200;
+
+    /** Set of known protocol GET params not to be stored into additionalReqParams} */
+    private static final Set<String> KNOWN_REQ_PARAMS = new HashSet<>();
+    static {
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.CLIENT_ID_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.REDIRECT_URI_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.STATE_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.SCOPE_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.LOGIN_HINT_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.PROMPT_PARAM);
+        KNOWN_REQ_PARAMS.add(AdapterConstants.KC_IDP_HINT);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.NONCE_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.MAX_AGE_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.UI_LOCALES_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.REQUEST_PARAM);
+        KNOWN_REQ_PARAMS.add(OIDCLoginProtocol.REQUEST_URI_PARAM);
+    }
+
+
+    public void parseRequest(AuthorizationEndpointRequest request) {
+        String clientId = getParameter(OIDCLoginProtocol.CLIENT_ID_PARAM);
+
+        if (request.clientId != null && !request.clientId.equals(clientId)) {
+            throw new IllegalArgumentException("The client_id parameter doesn't match the one from OIDC 'request' or 'request_uri'");
+        }
+
+        request.clientId = clientId;
+        request.responseType = replaceIfNotNull(request.responseType, getParameter(OIDCLoginProtocol.RESPONSE_TYPE_PARAM));
+        request.responseMode = replaceIfNotNull(request.responseMode, getParameter(OIDCLoginProtocol.RESPONSE_MODE_PARAM));
+        request.redirectUriParam = replaceIfNotNull(request.redirectUriParam, getParameter(OIDCLoginProtocol.REDIRECT_URI_PARAM));
+        request.state = replaceIfNotNull(request.state, getParameter(OIDCLoginProtocol.STATE_PARAM));
+        request.scope = replaceIfNotNull(request.scope, getParameter(OIDCLoginProtocol.SCOPE_PARAM));
+        request.loginHint = replaceIfNotNull(request.loginHint, getParameter(OIDCLoginProtocol.LOGIN_HINT_PARAM));
+        request.prompt = replaceIfNotNull(request.prompt, getParameter(OIDCLoginProtocol.PROMPT_PARAM));
+        request.idpHint = replaceIfNotNull(request.idpHint, getParameter(AdapterConstants.KC_IDP_HINT));
+        request.nonce = replaceIfNotNull(request.nonce, getParameter(OIDCLoginProtocol.NONCE_PARAM));
+        request.maxAge = replaceIfNotNull(request.maxAge, getIntParameter(OIDCLoginProtocol.MAX_AGE_PARAM));
+
+        extractAdditionalReqParams(request.additionalReqParams);
+    }
+
+
+    protected void extractAdditionalReqParams(Map<String, String> additionalReqParams) {
+        for (String paramName : keySet()) {
+            if (!KNOWN_REQ_PARAMS.contains(paramName)) {
+                String value = getParameter(paramName);
+                if (value != null && value.trim().isEmpty()) {
+                    value = null;
+                }
+                if (value != null && value.length() <= ADDITIONAL_REQ_PARAMS_MAX_SIZE) {
+                    if (additionalReqParams.size() >= ADDITIONAL_REQ_PARAMS_MAX_MUMBER) {
+                        logger.debug("Maximal number of additional OIDC params (" + ADDITIONAL_REQ_PARAMS_MAX_MUMBER + ") exceeded, ignoring rest of them!");
+                        break;
+                    }
+                    additionalReqParams.put(paramName, value);
+                } else {
+                    logger.debug("OIDC Additional param " + paramName + " ignored because value is empty or longer than " + ADDITIONAL_REQ_PARAMS_MAX_SIZE);
+                }
+            }
+
+        }
+    }
+
+    protected <T> T replaceIfNotNull(T previousVal, T newVal) {
+        return newVal==null ? previousVal : newVal;
+    }
+
+
+    protected abstract String getParameter(String paramName);
+
+    protected abstract Integer getIntParameter(String paramName);
+
+    protected abstract Set<String> keySet();
+
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
index ad23283..f5e4caa 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/UserInfoEndpoint.java
@@ -19,6 +19,7 @@ package org.keycloak.protocol.oidc.endpoints;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.HttpRequest;
 import org.jboss.resteasy.spi.HttpResponse;
+import org.keycloak.OAuth2Constants;
 import org.keycloak.common.ClientConnection;
 import org.keycloak.OAuthErrorException;
 import org.keycloak.RSATokenVerifier;
@@ -27,12 +28,15 @@ import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
 import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ErrorResponseException;
@@ -40,17 +44,18 @@ import org.keycloak.services.managers.AppAuthManager;
 import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.resources.Cors;
 import org.keycloak.services.Urls;
+import org.keycloak.utils.MediaType;
 
 import javax.ws.rs.GET;
 import javax.ws.rs.OPTIONS;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+
+import java.security.PrivateKey;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -86,7 +91,6 @@ public class UserInfoEndpoint {
 
     @Path("/")
     @OPTIONS
-    @Produces(MediaType.APPLICATION_JSON)
     public Response issueUserInfoPreflight() {
         return Cors.add(this.request, Response.ok()).auth().preflight().build();
     }
@@ -94,7 +98,6 @@ public class UserInfoEndpoint {
     @Path("/")
     @GET
     @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
     public Response issueUserInfoGet(@Context final HttpHeaders headers) {
         String accessToken = this.appAuthManager.extractAuthorizationHeaderToken(headers);
         return issueUserInfo(accessToken);
@@ -103,7 +106,6 @@ public class UserInfoEndpoint {
     @Path("/")
     @POST
     @NoCache
-    @Produces(MediaType.APPLICATION_JSON)
     public Response issueUserInfoPost() {
         // Try header first
         HttpHeaders headers = request.getHttpHeaders();
@@ -176,12 +178,39 @@ public class UserInfoEndpoint {
         AccessToken userInfo = new AccessToken();
         tokenManager.transformUserInfoAccessToken(session, userInfo, realm, clientModel, userModel, userSession, clientSession);
 
-        event.success();
-
         Map<String, Object> claims = new HashMap<String, Object>();
         claims.putAll(userInfo.getOtherClaims());
         claims.put("sub", userModel.getId());
-        return Cors.add(request, Response.ok(claims)).auth().allowedOrigins(token).build();
+
+        Response.ResponseBuilder responseBuilder;
+        OIDCAdvancedConfigWrapper cfg = OIDCAdvancedConfigWrapper.fromClientModel(clientModel);
+
+        if (cfg.isUserInfoSignatureRequired()) {
+            String issuerUrl = Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName());
+            String audience = clientModel.getClientId();
+            claims.put("iss", issuerUrl);
+            claims.put("aud", audience);
+
+            Algorithm signatureAlg = cfg.getUserInfoSignedResponseAlg();
+            PrivateKey privateKey = realm.getPrivateKey();
+
+            String signedUserInfo = new JWSBuilder()
+                    .jsonContent(claims)
+                    .sign(signatureAlg, privateKey);
+
+            responseBuilder = Response.ok(signedUserInfo).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JWT);
+
+            event.detail(Details.SIGNATURE_REQUIRED, "true");
+            event.detail(Details.SIGNATURE_ALGORITHM, cfg.getUserInfoSignedResponseAlg().toString());
+        } else {
+            responseBuilder = Response.ok(claims).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
+
+            event.detail(Details.SIGNATURE_REQUIRED, "false");
+        }
+
+        event.success();
+
+        return Cors.add(request, responseBuilder).auth().allowedOrigins(token).build();
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
index 56e7a48..f7475a9 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserAttributeMapper.java
@@ -19,10 +19,12 @@ package org.keycloak.protocol.oidc.mappers;
 
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperContainerModel;
 import org.keycloak.models.ProtocolMapperModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.ProtocolMapperConfigException;
 import org.keycloak.protocol.ProtocolMapperUtils;
 import org.keycloak.provider.ProviderConfigProperty;
 import org.keycloak.representations.AccessToken;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java
new file mode 100644
index 0000000..3233690
--- /dev/null
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCAdvancedConfigWrapper.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.protocol.oidc;
+
+import java.util.HashMap;
+
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.models.ClientModel;
+import org.keycloak.representations.idm.ClientRepresentation;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class OIDCAdvancedConfigWrapper {
+
+    private static final String USER_INFO_RESPONSE_SIGNATURE_ALG = "user.info.response.signature.alg";
+
+    private static final String REQUEST_OBJECT_SIGNATURE_ALG = "request.object.signature.alg";
+
+    private final ClientModel clientModel;
+    private final ClientRepresentation clientRep;
+
+    private OIDCAdvancedConfigWrapper(ClientModel client, ClientRepresentation clientRep) {
+        this.clientModel = client;
+        this.clientRep = clientRep;
+    }
+
+
+    public static OIDCAdvancedConfigWrapper fromClientModel(ClientModel client) {
+        return new OIDCAdvancedConfigWrapper(client, null);
+    }
+
+    public static OIDCAdvancedConfigWrapper fromClientRepresentation(ClientRepresentation clientRep) {
+        return new OIDCAdvancedConfigWrapper(null, clientRep);
+    }
+
+
+    public Algorithm getUserInfoSignedResponseAlg() {
+        String alg = getAttribute(USER_INFO_RESPONSE_SIGNATURE_ALG);
+        return alg==null ? null : Enum.valueOf(Algorithm.class, alg);
+    }
+
+    public void setUserInfoSignedResponseAlg(Algorithm alg) {
+        String algStr = alg==null ? null : alg.toString();
+        setAttribute(USER_INFO_RESPONSE_SIGNATURE_ALG, algStr);
+    }
+
+    public boolean isUserInfoSignatureRequired() {
+        return getUserInfoSignedResponseAlg() != null;
+    }
+
+    public Algorithm getRequestObjectSignatureAlg() {
+        String alg = getAttribute(REQUEST_OBJECT_SIGNATURE_ALG);
+        return alg==null ? null : Enum.valueOf(Algorithm.class, alg);
+    }
+
+    public void setRequestObjectSignatureAlg(Algorithm alg) {
+        String algStr = alg==null ? null : alg.toString();
+        setAttribute(REQUEST_OBJECT_SIGNATURE_ALG, algStr);
+    }
+
+
+    private String getAttribute(String attrKey) {
+        if (clientModel != null) {
+            return clientModel.getAttribute(attrKey);
+        } else {
+            return clientRep.getAttributes()==null ? null : clientRep.getAttributes().get(attrKey);
+        }
+    }
+
+    private void setAttribute(String attrKey, String attrValue) {
+        if (clientModel != null) {
+            if (attrValue != null) {
+                clientModel.setAttribute(attrKey, attrValue);
+            } else {
+                clientModel.removeAttribute(attrKey);
+            }
+        } else {
+            if (attrValue != null) {
+                if (clientRep.getAttributes() == null) {
+                    clientRep.setAttributes(new HashMap<>());
+                }
+                clientRep.getAttributes().put(attrKey, attrValue);
+            } else {
+                if (clientRep.getAttributes() != null) {
+                    clientRep.getAttributes().put(attrKey, null);
+                }
+            }
+        }
+    }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 3c4c3aa..c263405 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -66,6 +66,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
     public static final String REQUEST_PARAM = "request";
     public static final String REQUEST_URI_PARAM = "request_uri";
     public static final String UI_LOCALES_PARAM = OAuth2Constants.UI_LOCALES_PARAM;
+    public static final String CLAIMS_PARAM = "claims";
 
     public static final String LOGOUT_REDIRECT_URI = "OIDC_LOGOUT_REDIRECT_URI";
     public static final String ISSUER = "iss";
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
index eb5b5b4..800630c 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
@@ -48,6 +48,10 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
 
     public static final List<String> DEFAULT_ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED = list(Algorithm.RS256.toString());
 
+    public static final List<String> DEFAULT_USER_INFO_SIGNING_ALG_VALUES_SUPPORTED  = list(Algorithm.RS256.toString());
+
+    public static final List<String> DEFAULT_REQUEST_OBJECT_SIGNING_ALG_VALUES_SUPPORTED  = list(Algorithm.none.toString(), Algorithm.RS256.toString());
+
     public static final List<String> DEFAULT_GRANT_TYPES_SUPPORTED = list(OAuth2Constants.AUTHORIZATION_CODE, OAuth2Constants.IMPLICIT, OAuth2Constants.REFRESH_TOKEN, OAuth2Constants.PASSWORD, OAuth2Constants.CLIENT_CREDENTIALS);
 
     public static final List<String> DEFAULT_RESPONSE_TYPES_SUPPORTED = list(OAuth2Constants.CODE, OIDCResponseType.NONE, OIDCResponseType.ID_TOKEN, OIDCResponseType.TOKEN, "id_token token", "code id_token", "code token", "code id_token token");
@@ -90,6 +94,8 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
         config.setRegistrationEndpoint(RealmsResource.clientRegistrationUrl(uriInfo).path(ClientRegistrationService.class, "provider").build(realm.getName(), OIDCClientRegistrationProviderFactory.ID).toString());
 
         config.setIdTokenSigningAlgValuesSupported(DEFAULT_ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED);
+        config.setUserInfoSigningAlgValuesSupported(DEFAULT_USER_INFO_SIGNING_ALG_VALUES_SUPPORTED);
+        config.setRequestObjectSigningAlgValuesSupported(DEFAULT_REQUEST_OBJECT_SIGNING_ALG_VALUES_SUPPORTED);
         config.setResponseTypesSupported(DEFAULT_RESPONSE_TYPES_SUPPORTED);
         config.setSubjectTypesSupported(DEFAULT_SUBJECT_TYPES_SUPPORTED);
         config.setResponseModesSupported(DEFAULT_RESPONSE_MODES_SUPPORTED);
@@ -104,8 +110,8 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
 
         config.setScopesSupported(SCOPES_SUPPORTED);
 
-        config.setRequestParameterSupported(false);
-        config.setRequestUriParameterSupported(false);
+        config.setRequestParameterSupported(true);
+        config.setRequestUriParameterSupported(true);
 
         return config;
     }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
index 0421e16..181e0d2 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
@@ -64,6 +64,12 @@ public class OIDCConfigurationRepresentation {
     @JsonProperty("id_token_signing_alg_values_supported")
     private List<String> idTokenSigningAlgValuesSupported;
 
+    @JsonProperty("userinfo_signing_alg_values_supported")
+    private List<String> userInfoSigningAlgValuesSupported;
+
+    @JsonProperty("request_object_signing_alg_values_supported")
+    private List<String> requestObjectSigningAlgValuesSupported;
+
     @JsonProperty("response_modes_supported")
     private List<String> responseModesSupported;
 
@@ -184,6 +190,22 @@ public class OIDCConfigurationRepresentation {
         this.idTokenSigningAlgValuesSupported = idTokenSigningAlgValuesSupported;
     }
 
+    public List<String> getUserInfoSigningAlgValuesSupported() {
+        return userInfoSigningAlgValuesSupported;
+    }
+
+    public void setUserInfoSigningAlgValuesSupported(List<String> userInfoSigningAlgValuesSupported) {
+        this.userInfoSigningAlgValuesSupported = userInfoSigningAlgValuesSupported;
+    }
+
+    public List<String> getRequestObjectSigningAlgValuesSupported() {
+        return requestObjectSigningAlgValuesSupported;
+    }
+
+    public void setRequestObjectSigningAlgValuesSupported(List<String> requestObjectSigningAlgValuesSupported) {
+        this.requestObjectSigningAlgValuesSupported = requestObjectSigningAlgValuesSupported;
+    }
+
     public List<String> getResponseModesSupported() {
         return responseModesSupported;
     }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java
index c856a81..d8f7fe7 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/JWKSUtils.java
@@ -18,12 +18,15 @@
 package org.keycloak.protocol.oidc.utils;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.security.PublicKey;
 
-import org.keycloak.broker.provider.util.SimpleHttp;
+import org.keycloak.common.util.StreamUtil;
+import org.keycloak.connections.httpclient.HttpClientProvider;
 import org.keycloak.jose.jwk.JSONWebKeySet;
 import org.keycloak.jose.jwk.JWK;
 import org.keycloak.jose.jwk.JWKParser;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.util.JsonSerialization;
 
 /**
@@ -31,8 +34,9 @@ import org.keycloak.util.JsonSerialization;
  */
 public class JWKSUtils {
 
-    public static JSONWebKeySet sendJwksRequest(String jwksURI) throws IOException {
-        String keySetString = SimpleHttp.doGet(jwksURI).asString();
+    public static JSONWebKeySet sendJwksRequest(KeycloakSession session, String jwksURI) throws IOException {
+        InputStream is = session.getProvider(HttpClientProvider.class).get(jwksURI);
+        String keySetString = StreamUtil.readString(is);
         return JsonSerialization.readValue(keySetString, JSONWebKeySet.class);
     }
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
index 441cd57..b7d9ad4 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/utils/RedirectUtils.java
@@ -77,7 +77,7 @@ public class RedirectUtils {
         } else {
             redirectUri = lowerCaseHostname(redirectUri);
 
-            String r = redirectUri.indexOf('?') != -1 ? redirectUri.substring(0, redirectUri.indexOf('?')) : redirectUri;
+            String r = redirectUri;
             Set<String> resolveValidRedirects = resolveValidRedirects(uriInfo, rootUrl, validRedirects);
 
             boolean valid = matchesRedirects(resolveValidRedirects, r);
@@ -134,15 +134,17 @@ public class RedirectUtils {
 
     private static boolean matchesRedirects(Set<String> validRedirects, String redirect) {
         for (String validRedirect : validRedirects) {
-            if (validRedirect.endsWith("*")) {
+            if (validRedirect.endsWith("*") && !validRedirect.contains("?")) {
+                // strip off the query component - we don't check them when wildcards are effective
+                String r = redirect.contains("?") ? redirect.substring(0, redirect.indexOf("?")) : redirect;
                 // strip off *
                 int length = validRedirect.length() - 1;
                 validRedirect = validRedirect.substring(0, length);
-                if (redirect.startsWith(validRedirect)) return true;
+                if (r.startsWith(validRedirect)) return true;
                 // strip off trailing '/'
                 if (length - 1 > 0 && validRedirect.charAt(length - 1) == '/') length--;
                 validRedirect = validRedirect.substring(0, length);
-                if (validRedirect.equals(redirect)) return true;
+                if (validRedirect.equals(r)) return true;
             } else if (validRedirect.equals(redirect)) return true;
         }
         return false;
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
index 88b5a34..d634b00 100755
--- a/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
@@ -29,8 +29,12 @@ import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ForbiddenException;
+import org.keycloak.services.resources.admin.AdminRoot;
+import org.keycloak.services.validation.ClientValidator;
+import org.keycloak.services.validation.ValidationMessages;
 
 import javax.ws.rs.core.Response;
+import java.util.Properties;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -50,6 +54,16 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
 
         auth.requireCreate();
 
+        ValidationMessages validationMessages = new ValidationMessages();
+        if (!ClientValidator.validate(client, validationMessages)) {
+            String errorCode = validationMessages.fieldHasError("redirectUris") ? ErrorCodes.INVALID_REDIRECT_URI : ErrorCodes.INVALID_CLIENT_METADATA;
+            throw new ErrorResponseException(
+                    errorCode,
+                    validationMessages.getStringMessages(),
+                    Response.Status.BAD_REQUEST
+            );
+        }
+
         try {
             ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true);
 
@@ -104,6 +118,16 @@ public abstract class AbstractClientRegistrationProvider implements ClientRegist
             throw new ErrorResponseException(ErrorCodes.INVALID_CLIENT_METADATA, "Client Identifier modified", Response.Status.BAD_REQUEST);
         }
 
+        ValidationMessages validationMessages = new ValidationMessages();
+        if (!ClientValidator.validate(rep, validationMessages)) {
+            String errorCode = validationMessages.fieldHasError("redirectUris") ? ErrorCodes.INVALID_REDIRECT_URI : ErrorCodes.INVALID_CLIENT_METADATA;
+            throw new ErrorResponseException(
+                    errorCode,
+                    validationMessages.getStringMessages(),
+                    Response.Status.BAD_REQUEST
+            );
+        }
+
         RepresentationToModel.updateClient(rep, client);
         rep = ModelToRepresentation.toRepresentation(client);
 
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
index 3ddcc59..e1939ef 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
@@ -24,8 +24,10 @@ import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthen
 import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
 import org.keycloak.jose.jwk.JSONWebKeySet;
 import org.keycloak.jose.jwk.JWK;
+import org.keycloak.jose.jws.Algorithm;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.protocol.oidc.utils.AuthorizeClientUtil;
 import org.keycloak.protocol.oidc.utils.JWKSUtils;
@@ -87,14 +89,12 @@ public class DescriptionConverter {
         }
         client.setClientAuthenticatorType(clientAuthFactory.getId());
 
-        // Externalize to ClientAuthenticator itself?
-        if (authMethod != null && authMethod.equals(OIDCLoginProtocol.PRIVATE_KEY_JWT)) {
-
-            PublicKey publicKey = retrievePublicKey(clientOIDC);
-            if (publicKey == null) {
-                throw new ClientRegistrationException("Didn't find key of supported keyType for use " + JWK.Use.SIG.asString());
-            }
+        PublicKey publicKey = retrievePublicKey(session, clientOIDC);
+        if (authMethod != null && authMethod.equals(OIDCLoginProtocol.PRIVATE_KEY_JWT) && publicKey == null) {
+            throw new ClientRegistrationException("Didn't find key of supported keyType for use " + JWK.Use.SIG.asString());
+        }
 
+        if (publicKey != null) {
             String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
 
             CertificateRepresentation rep = new CertificateRepresentation();
@@ -102,13 +102,24 @@ public class DescriptionConverter {
             CertificateInfoHelper.updateClientRepresentationCertificateInfo(client, rep, JWTClientAuthenticator.ATTR_PREFIX);
         }
 
+        OIDCAdvancedConfigWrapper configWrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
+        if (clientOIDC.getUserinfoSignedResponseAlg() != null) {
+            Algorithm algorithm = Enum.valueOf(Algorithm.class, clientOIDC.getUserinfoSignedResponseAlg());
+            configWrapper.setUserInfoSignedResponseAlg(algorithm);
+        }
+
+        if (clientOIDC.getRequestObjectSigningAlg() != null) {
+            Algorithm algorithm = Enum.valueOf(Algorithm.class, clientOIDC.getRequestObjectSigningAlg());
+            configWrapper.setRequestObjectSignatureAlg(algorithm);
+        }
+
         return client;
     }
 
 
-    private static PublicKey retrievePublicKey(OIDCClientRepresentation clientOIDC) {
+    private static PublicKey retrievePublicKey(KeycloakSession session, OIDCClientRepresentation clientOIDC) {
         if (clientOIDC.getJwksUri() == null && clientOIDC.getJwks() == null) {
-            throw new ClientRegistrationException("Requested client authentication method '%s' but jwks_uri nor jwks were available in config");
+            return null;
         }
 
         if (clientOIDC.getJwksUri() != null && clientOIDC.getJwks() != null) {
@@ -120,7 +131,7 @@ public class DescriptionConverter {
             keySet = clientOIDC.getJwks();
         } else {
             try {
-                keySet = JWKSUtils.sendJwksRequest(clientOIDC.getJwksUri());
+                keySet = JWKSUtils.sendJwksRequest(session, clientOIDC.getJwksUri());
             } catch (IOException ioe) {
                 throw new ClientRegistrationException("Failed to send JWKS request to specified jwks_uri", ioe);
             }
@@ -152,6 +163,15 @@ public class DescriptionConverter {
         response.setRegistrationClientUri(uri.toString());
         response.setResponseTypes(getOIDCResponseTypes(client));
         response.setGrantTypes(getOIDCGrantTypes(client));
+
+        OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
+        if (config.isUserInfoSignatureRequired()) {
+            response.setUserinfoSignedResponseAlg(config.getUserInfoSignedResponseAlg().toString());
+        }
+        if (config.getRequestObjectSignatureAlg() != null) {
+            response.setRequestObjectSigningAlg(config.getRequestObjectSignatureAlg().toString());
+        }
+
         return response;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
index f29ed8c..152d632 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientAttributeCertificateResource.java
@@ -66,6 +66,10 @@ import java.util.Map;
  */
 public class ClientAttributeCertificateResource {
 
+    public static final String CERTIFICATE_PEM = "Certificate PEM";
+    public static final String PUBLIC_KEY_PEM = "Public Key PEM";
+    public static final String JSON_WEB_KEY_SET = "JSON Web Key Set";
+
     protected RealmModel realm;
     private RealmAuth auth;
     protected ClientModel client;
@@ -195,12 +199,23 @@ public class ClientAttributeCertificateResource {
         Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
         String keystoreFormat = uploadForm.get("keystoreFormat").get(0).getBodyAsString();
         List<InputPart> inputParts = uploadForm.get("file");
-        if (keystoreFormat.equals("Certificate PEM")) {
+        if (keystoreFormat.equals(CERTIFICATE_PEM)) {
             String pem = StreamUtil.readString(inputParts.get(0).getBody(InputStream.class, null));
+
+            // Validate format
+            KeycloakModelUtils.getCertificate(pem);
+
             info.setCertificate(pem);
             return info;
+        } else if (keystoreFormat.equals(PUBLIC_KEY_PEM)) {
+            String pem = StreamUtil.readString(inputParts.get(0).getBody(InputStream.class, null));
+
+            // Validate format
+            KeycloakModelUtils.getPublicKey(pem);
 
-        } else if (keystoreFormat.equals("JSON Web Key Set (JWK)")) {
+            info.setPublicKey(pem);
+            return info;
+        } else if (keystoreFormat.equals(JSON_WEB_KEY_SET)) {
             InputStream stream = inputParts.get(0).getBody(InputStream.class, null);
             JSONWebKeySet keySet = JsonSerialization.readValue(stream, JSONWebKeySet.class);
             PublicKey publicKey = JWKSUtils.getKeyForUse(keySet, JWK.Use.SIG);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
index fc5b3c9..9b6593f 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java
@@ -40,6 +40,7 @@ import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
 import org.keycloak.representations.idm.UserSessionRepresentation;
+import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.clientregistration.ClientRegistrationTokenUtils;
 import org.keycloak.services.managers.ClientManager;
@@ -48,6 +49,8 @@ import org.keycloak.services.managers.ResourceAdminManager;
 import org.keycloak.services.resources.KeycloakApplication;
 import org.keycloak.services.ErrorResponse;
 import org.keycloak.common.util.Time;
+import org.keycloak.services.validation.ClientValidator;
+import org.keycloak.services.validation.ValidationMessages;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
@@ -63,10 +66,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import static java.lang.Boolean.TRUE;
 
@@ -107,7 +107,7 @@ public class ClientResource {
 
     @Path("protocol-mappers")
     public ProtocolMappersResource getProtocolMappers() {
-        ProtocolMappersResource mappers = new ProtocolMappersResource(client, auth, adminEvent);
+        ProtocolMappersResource mappers = new ProtocolMappersResource(realm, client, auth, adminEvent);
         ResteasyProviderFactory.getInstance().injectProperties(mappers);
         return mappers;
     }
@@ -126,6 +126,16 @@ public class ClientResource {
             throw new NotFoundException("Could not find client");
         }
 
+        ValidationMessages validationMessages = new ValidationMessages();
+        if (!ClientValidator.validate(rep, validationMessages)) {
+            Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+            throw new ErrorResponseException(
+                    validationMessages.getStringMessages(),
+                    validationMessages.getStringMessages(messages),
+                    Response.Status.BAD_REQUEST
+            );
+        }
+
         try {
             updateClientFromRep(rep, client, session);
             adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
index 207f8d1..dacea26 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientsResource.java
@@ -17,7 +17,6 @@
 package org.keycloak.services.resources.admin;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
-import org.jboss.resteasy.spi.NotFoundException;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
@@ -28,16 +27,13 @@ import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.managers.ClientManager;
+import org.keycloak.services.validation.ClientValidator;
+import org.keycloak.services.validation.ValidationMessages;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.*;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -45,6 +41,7 @@ import javax.ws.rs.core.UriInfo;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Properties;
 
 /**
  * Base resource class for managing a realm's clients.
@@ -122,6 +119,16 @@ public class ClientsResource {
     public Response createClient(final @Context UriInfo uriInfo, final ClientRepresentation rep) {
         auth.requireManage();
 
+        ValidationMessages validationMessages = new ValidationMessages();
+        if (!ClientValidator.validate(rep, validationMessages)) {
+            Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+            throw new ErrorResponseException(
+                    validationMessages.getStringMessages(),
+                    validationMessages.getStringMessages(messages),
+                    Response.Status.BAD_REQUEST
+            );
+        }
+
         try {
             ClientModel clientModel = ClientManager.createClient(session, realm, rep, true);
 
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
index baf9bb6..761e307 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientTemplateResource.java
@@ -81,7 +81,7 @@ public class ClientTemplateResource {
 
     @Path("protocol-mappers")
     public ProtocolMappersResource getProtocolMappers() {
-        ProtocolMappersResource mappers = new ProtocolMappersResource(template, auth, adminEvent);
+        ProtocolMappersResource mappers = new ProtocolMappersResource(realm, template, auth, adminEvent);
         ResteasyProviderFactory.getInstance().injectProperties(mappers);
         return mappers;
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
index 958a849..8e7c9ac 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
@@ -116,7 +116,7 @@ public class IdentityProvidersResource {
         InputPart file = formDataMap.get("file").get(0);
         InputStream inputStream = file.getBody(InputStream.class, null);
         IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
-        Map<String, String> config = providerFactory.parseConfig(inputStream);
+        Map<String, String> config = providerFactory.parseConfig(session, inputStream);
         return config;
     }
 
@@ -143,7 +143,7 @@ public class IdentityProvidersResource {
         try {
             IdentityProviderFactory providerFactory = getProviderFactorytById(providerId);
             Map<String, String> config;
-            config = providerFactory.parseConfig(inputStream);
+            config = providerFactory.parseConfig(session, inputStream);
             return config;
         } finally {
             try {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
index b9da2bf..86dcefc 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ProtocolMappersResource.java
@@ -20,14 +20,22 @@ import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.spi.NotFoundException;
 import org.keycloak.events.admin.OperationType;
 import org.keycloak.events.admin.ResourceType;
+import org.keycloak.mappers.FederationConfigValidationException;
+import org.keycloak.mappers.UserFederationMapper;
+import org.keycloak.mappers.UserFederationMapperFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.ProtocolMapperContainerModel;
 import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserFederationMapperModel;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.ProtocolMapper;
+import org.keycloak.protocol.ProtocolMapperConfigException;
 import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.services.ErrorResponse;
+import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.ServicesLogger;
 import org.keycloak.services.resources.admin.RealmAuth.Resource;
 
@@ -44,8 +52,10 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import java.text.MessageFormat;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Properties;
 
 /**
  * Base resource for managing users
@@ -56,6 +66,8 @@ import java.util.List;
 public class ProtocolMappersResource {
     protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
 
+    protected RealmModel realm;
+
     protected ProtocolMapperContainerModel client;
 
     protected RealmAuth auth;
@@ -68,7 +80,8 @@ public class ProtocolMappersResource {
     @Context
     protected KeycloakSession session;
 
-    public ProtocolMappersResource(ProtocolMapperContainerModel client, RealmAuth auth, AdminEventBuilder adminEvent) {
+    public ProtocolMappersResource(RealmModel realm, ProtocolMapperContainerModel client, RealmAuth auth, AdminEventBuilder adminEvent) {
+        this.realm = realm;
         this.auth = auth;
         this.client = client;
         this.adminEvent = adminEvent.resource(ResourceType.PROTOCOL_MAPPER);
@@ -119,6 +132,7 @@ public class ProtocolMappersResource {
         ProtocolMapperModel model = null;
         try {
             model = RepresentationToModel.toModel(rep);
+            validateModel(model);
             model = client.addProtocolMapper(model);
             adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
 
@@ -146,6 +160,7 @@ public class ProtocolMappersResource {
         ProtocolMapperModel model = null;
         for (ProtocolMapperRepresentation rep : reps) {
             model = RepresentationToModel.toModel(rep);
+            validateModel(model);
             model = client.addProtocolMapper(model);
         }
         adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(reps).success();
@@ -216,6 +231,9 @@ public class ProtocolMappersResource {
         ProtocolMapperModel model = client.getProtocolMapperById(id);
         if (model == null) throw new NotFoundException("Model not found");
         model = RepresentationToModel.toModel(rep);
+
+        validateModel(model);
+
         client.updateProtocolMapper(model);
         adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
     }
@@ -242,4 +260,18 @@ public class ProtocolMappersResource {
 
     }
 
+    private void validateModel(ProtocolMapperModel model) {
+        try {
+            ProtocolMapper mapper = (ProtocolMapper)session.getKeycloakSessionFactory().getProviderFactory(ProtocolMapper.class, model.getProtocolMapper());
+            if (mapper != null) {
+                mapper.validateConfig(session, realm, client, model);
+            }
+        } catch (ProtocolMapperConfigException ex) {
+            logger.error(ex.getMessage());
+            Properties messages = AdminRoot.getMessages(session, realm, auth.getAuth().getToken().getLocale());
+            throw new ErrorResponseException(ex.getMessage(), MessageFormat.format(messages.getProperty(ex.getMessage(), ex.getMessage()), ex.getParameters()),
+                    Response.Status.BAD_REQUEST);
+        }
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index 5e1cd9f..6cdf52e 100644
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -56,15 +56,22 @@ import java.io.*;
 import java.net.URI;
 import java.net.URL;
 import java.util.*;
+import org.jboss.dmr.ModelNode;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
 public class KeycloakApplication extends Application {
+    // This param name is defined again in Keycloak Server Subsystem class
+    // org.keycloak.subsystem.server.extension.KeycloakServerDeploymentProcessor.  We have this value in
+    // two places to avoid dependency between Keycloak Subsystem and Keycloak Services module.
+    public static final String KEYCLOAK_CONFIG_PARAM_NAME = "org.keycloak.server-subsystem.Config";
 
     private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
 
+    protected boolean embedded = false;
+
     protected Set<Object> singletons = new HashSet<Object>();
     protected Set<Class<?>> classes = new HashSet<Class<?>>();
 
@@ -72,69 +79,79 @@ public class KeycloakApplication extends Application {
     protected String contextPath;
 
     public KeycloakApplication(@Context ServletContext context, @Context Dispatcher dispatcher) {
-        loadConfig();
+        try {
+            if ("true".equals(context.getInitParameter("keycloak.embedded"))) {
+                embedded = true;
+            }
 
-        this.contextPath = context.getContextPath();
-        this.sessionFactory = createSessionFactory();
+            loadConfig(context);
 
-        dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
-        ResteasyProviderFactory.pushContext(KeycloakApplication.class, this); // for injection
-        context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory);
+            this.contextPath = context.getContextPath();
+            this.sessionFactory = createSessionFactory();
 
-        singletons.add(new ServerVersionResource());
-        singletons.add(new RobotsResource());
-        singletons.add(new RealmsResource());
-        singletons.add(new AdminRoot());
-        classes.add(ThemeResource.class);
-        classes.add(JsResource.class);
+            dispatcher.getDefaultContextObjects().put(KeycloakApplication.class, this);
+            ResteasyProviderFactory.pushContext(KeycloakApplication.class, this); // for injection
+            context.setAttribute(KeycloakSessionFactory.class.getName(), this.sessionFactory);
 
-        classes.add(KeycloakTransactionCommitter.class);
+            singletons.add(new ServerVersionResource());
+            singletons.add(new RobotsResource());
+            singletons.add(new RealmsResource());
+            singletons.add(new AdminRoot());
+            classes.add(ThemeResource.class);
+            classes.add(JsResource.class);
 
-        singletons.add(new ObjectMapperResolver(Boolean.parseBoolean(System.getProperty("keycloak.jsonPrettyPrint", "false"))));
+            classes.add(KeycloakTransactionCommitter.class);
 
-        ExportImportManager[] exportImportManager = new ExportImportManager[1];
+            singletons.add(new ObjectMapperResolver(Boolean.parseBoolean(System.getProperty("keycloak.jsonPrettyPrint", "false"))));
 
-        KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
+            ExportImportManager[] exportImportManager = new ExportImportManager[1];
 
-            @Override
-            public void run(KeycloakSession lockSession) {
-                DBLockManager dbLockManager = new DBLockManager(lockSession);
-                dbLockManager.checkForcedUnlock();
-                DBLockProvider dbLock = dbLockManager.getDBLock();
-                dbLock.waitForLock();
-                try {
-                    exportImportManager[0] = migrateAndBootstrap();
-                } finally {
-                    dbLock.releaseLock();
+            KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
+
+                @Override
+                public void run(KeycloakSession lockSession) {
+                    DBLockManager dbLockManager = new DBLockManager(lockSession);
+                    dbLockManager.checkForcedUnlock();
+                    DBLockProvider dbLock = dbLockManager.getDBLock();
+                    dbLock.waitForLock();
+                    try {
+                        exportImportManager[0] = migrateAndBootstrap();
+                    } finally {
+                        dbLock.releaseLock();
+                    }
                 }
-            }
 
-        });
+            });
 
 
-        if (exportImportManager[0].isRunExport()) {
-            exportImportManager[0].runExport();
-        }
+            if (exportImportManager[0].isRunExport()) {
+                exportImportManager[0].runExport();
+            }
 
-        boolean bootstrapAdminUser = false;
-        KeycloakSession session = sessionFactory.create();
-        try {
-            session.getTransactionManager().begin();
-            bootstrapAdminUser = new ApplianceBootstrap(session).isNoMasterUser();
+            boolean bootstrapAdminUser = false;
+            KeycloakSession session = sessionFactory.create();
+            try {
+                session.getTransactionManager().begin();
+                bootstrapAdminUser = new ApplianceBootstrap(session).isNoMasterUser();
 
-            session.getTransactionManager().commit();
-        } finally {
-            session.close();
-        }
+                session.getTransactionManager().commit();
+            } finally {
+                session.close();
+            }
 
-        sessionFactory.publish(new PostMigrationEvent());
+            sessionFactory.publish(new PostMigrationEvent());
 
-        singletons.add(new WelcomeResource(bootstrapAdminUser));
+            singletons.add(new WelcomeResource(bootstrapAdminUser));
 
-        setupScheduledTasks(sessionFactory);
+            setupScheduledTasks(sessionFactory);
+        } catch (Throwable t) {
+            if (!embedded) {
+                exit(1);
+            }
+            throw t;
+        }
     }
 
-
     // Migrate model, bootstrap master realm, import realms and create admin user. This is done with acquired dbLock
     protected ExportImportManager migrateAndBootstrap() {
         ExportImportManager exportImportManager;
@@ -185,7 +202,6 @@ public class KeycloakApplication extends Application {
             session.getTransactionManager().commit();
         } catch (Exception e) {
             session.getTransactionManager().rollback();
-            logger.migrationFailure(e);
             throw e;
         } finally {
             session.close();
@@ -206,12 +222,18 @@ public class KeycloakApplication extends Application {
         return uriInfo.getBaseUriBuilder().replacePath(getContextPath()).build();
     }
 
-    public static void loadConfig() {
+    public static void loadConfig(ServletContext context) {
         try {
             JsonNode node = null;
+            
+            String dmrConfig = loadDmrConfig(context);
+            if (dmrConfig != null) {
+                node = new ObjectMapper().readTree(dmrConfig);
+                logger.loadingFrom("standalone.xml or domain.xml");
+            }
 
             String configDir = System.getProperty("jboss.server.config.dir");
-            if (configDir != null) {
+            if (node == null && configDir != null) {
                 File f = new File(configDir + File.separator + "keycloak-server.json");
                 if (f.isFile()) {
                     logger.loadingFrom(f.getAbsolutePath());
@@ -230,14 +252,24 @@ public class KeycloakApplication extends Application {
             if (node != null) {
                 Properties properties = new SystemEnvProperties();
                 Config.init(new JsonConfigProvider(node, properties));
-                return;
             } else {
-                throw new RuntimeException("Config 'keycloak-server.json' not found");
+                throw new RuntimeException("Keycloak config not found.");
             }
         } catch (IOException e) {
             throw new RuntimeException("Failed to load config", e);
         }
     }
+    
+    private static String loadDmrConfig(ServletContext context) {
+        String dmrConfig = context.getInitParameter(KEYCLOAK_CONFIG_PARAM_NAME);
+        if (dmrConfig == null) return null;
+
+        ModelNode dmrConfigNode = ModelNode.fromString(dmrConfig);
+        if (dmrConfigNode.asPropertyList().isEmpty()) return null;
+        
+        // note that we need to resolve expressions BEFORE we convert to JSON
+        return dmrConfigNode.resolve().toJSONString(true);
+    }
 
     public static KeycloakSessionFactory createSessionFactory() {
         DefaultKeycloakSessionFactory factory = new DefaultKeycloakSessionFactory();
@@ -386,4 +418,13 @@ public class KeycloakApplication extends Application {
         }
     }
 
+    private void exit(int status) {
+        new Thread() {
+            @Override
+            public void run() {
+                System.exit(status);
+            }
+        }.start();
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/ServicesLogger.java b/services/src/main/java/org/keycloak/services/ServicesLogger.java
index de7eef7..af6c4c1 100644
--- a/services/src/main/java/org/keycloak/services/ServicesLogger.java
+++ b/services/src/main/java/org/keycloak/services/ServicesLogger.java
@@ -430,4 +430,8 @@ public interface ServicesLogger extends BasicLogger {
     @Message(id=96, value="Not found JWK of supported keyType under jwks_uri for usage: %s")
     void supportedJwkNotFound(String usage);
 
+    @LogMessage(level = WARN)
+    @Message(id=97, value="Invalid request")
+    void invalidRequest(@Cause Throwable t);
+
 }
diff --git a/services/src/main/java/org/keycloak/services/util/CertificateInfoHelper.java b/services/src/main/java/org/keycloak/services/util/CertificateInfoHelper.java
index b309927..359d28d 100644
--- a/services/src/main/java/org/keycloak/services/util/CertificateInfoHelper.java
+++ b/services/src/main/java/org/keycloak/services/util/CertificateInfoHelper.java
@@ -17,9 +17,18 @@
 
 package org.keycloak.services.util;
 
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
 import java.util.HashMap;
 
+import javax.ws.rs.core.Response;
+
+import org.keycloak.authentication.AuthenticationFlowError;
+import org.keycloak.authentication.ClientAuthenticationFlowContext;
+import org.keycloak.authentication.authenticators.client.ClientAuthUtil;
 import org.keycloak.models.ClientModel;
+import org.keycloak.models.ModelException;
+import org.keycloak.models.utils.KeycloakModelUtils;
 import org.keycloak.representations.idm.CertificateRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
 
@@ -34,6 +43,8 @@ public class CertificateInfoHelper {
     public static final String PUBLIC_KEY = "public.key";
 
 
+    // CLIENT MODEL METHODS
+
     public static CertificateRepresentation getCertificateFromClient(ClientModel client, String attributePrefix) {
         String privateKeyAttribute = attributePrefix + "." + PRIVATE_KEY;
         String certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
@@ -75,6 +86,32 @@ public class CertificateInfoHelper {
     }
 
 
+    public static PublicKey getSignatureValidationKey(ClientModel client, String attributePrefix) throws ModelException {
+        CertificateRepresentation certInfo = getCertificateFromClient(client, attributePrefix);
+
+        String encodedCertificate = certInfo.getCertificate();
+        String encodedPublicKey = certInfo.getPublicKey();
+
+        if (encodedCertificate == null && encodedPublicKey == null) {
+            throw new ModelException("Client doesn't have certificate or publicKey configured");
+        }
+
+        if (encodedCertificate != null && encodedPublicKey != null) {
+            throw new ModelException("Client has both publicKey and certificate configured");
+        }
+
+        // TODO: Caching of publicKeys / certificates, so it doesn't need to be always computed from pem. For performance reasons...
+        if (encodedCertificate != null) {
+            X509Certificate clientCert = KeycloakModelUtils.getCertificate(encodedCertificate);
+            return clientCert.getPublicKey();
+        } else {
+            return KeycloakModelUtils.getPublicKey(encodedPublicKey);
+        }
+    }
+
+
+    // CLIENT REPRESENTATION METHODS
+
     public static void updateClientRepresentationCertificateInfo(ClientRepresentation client, CertificateRepresentation rep, String attributePrefix) {
         String privateKeyAttribute = attributePrefix + "." + PRIVATE_KEY;
         String certificateAttribute = attributePrefix + "." + X509CERTIFICATE;
diff --git a/services/src/main/java/org/keycloak/services/validation/ClientValidator.java b/services/src/main/java/org/keycloak/services/validation/ClientValidator.java
new file mode 100644
index 0000000..22290c5
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/validation/ClientValidator.java
@@ -0,0 +1,54 @@
+/*
+ *
+ *  * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ *  * and other contributors as indicated by the @author tags.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  * http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.keycloak.services.validation;
+
+import org.keycloak.representations.idm.ClientRepresentation;
+
+/**
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
+ */
+public class ClientValidator {
+    /**
+     * Checks if the Client's Redirect URIs doesn't contain any URI fragments (like http://example.org/auth#fragment)
+     *
+     * @see <a href="https://issues.jboss.org/browse/KEYCLOAK-3421">KEYCLOAK-3421</a>
+     * @param client
+     * @param messages
+     * @return true if Redirect URIs doesn't contain any URI with fragments
+     */
+    public static boolean validate(ClientRepresentation client, ValidationMessages messages) {
+        boolean isValid = true;
+
+        if (client.getRedirectUris() != null) {
+            long urisWithFragmentCount = client.getRedirectUris().stream().filter(p -> p.contains("#")).count();
+            if (urisWithFragmentCount > 0) {
+                messages.add("redirectUris", "Redirect URIs must not contain an URI fragment", "clientRedirectURIsFragmentError");
+                isValid = false;
+            }
+        }
+
+        if (client.getRootUrl() != null && client.getRootUrl().contains("#")) {
+            messages.add("rootUrl", "Root URL must not contain an URL fragment", "clientRootURLFragmentError");
+            isValid = false;
+        }
+
+        return isValid;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/validation/ValidationMessage.java b/services/src/main/java/org/keycloak/services/validation/ValidationMessage.java
new file mode 100644
index 0000000..7e4dac1
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/validation/ValidationMessage.java
@@ -0,0 +1,100 @@
+/*
+ *
+ *  * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ *  * and other contributors as indicated by the @author tags.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  * http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.keycloak.services.validation;
+
+import java.text.MessageFormat;
+import java.util.Properties;
+
+/**
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
+ */
+public class ValidationMessage {
+    private String fieldId;
+    private String message;
+    private String localizedMessageKey;
+    private Object[] localizedMessageParameters;
+
+    public ValidationMessage(String message) {
+        this.message = message;
+    }
+
+    public ValidationMessage(String message, String localizedMessageKey, Object... localizedMessageParameters) {
+        this.message = message;
+        this.localizedMessageKey = localizedMessageKey;
+        this.localizedMessageParameters = localizedMessageParameters;
+    }
+
+    public String getFieldId() {
+        return fieldId;
+    }
+
+    public void setFieldId(String fieldId) {
+        this.fieldId = fieldId;
+    }
+
+    public String getLocalizedMessageKey() {
+        return localizedMessageKey;
+    }
+
+    public void setLocalizedMessageKey(String localizedMessageKey) {
+        this.localizedMessageKey = localizedMessageKey;
+    }
+
+    public Object[] getLocalizedMessageParameters() {
+        return localizedMessageParameters;
+    }
+
+    public void setLocalizedMessageParameters(Object[] localizedMessageParameters) {
+        this.localizedMessageParameters = localizedMessageParameters;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getMessage(Properties localizedMessages) {
+        if (getLocalizedMessageKey() != null) {
+            return MessageFormat.format(localizedMessages.getProperty(getLocalizedMessageKey(), getMessage()), getLocalizedMessageParameters());
+        }
+        else {
+            return getMessage();
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ValidationMessage message1 = (ValidationMessage) o;
+
+        if (getFieldId() != null ? !getFieldId().equals(message1.getFieldId()) : message1.getFieldId() != null)
+            return false;
+        return getMessage() != null ? getMessage().equals(message1.getMessage()) : message1.getMessage() == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = getFieldId() != null ? getFieldId().hashCode() : 0;
+        result = 31 * result + (getMessage() != null ? getMessage().hashCode() : 0);
+        return result;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java b/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java
new file mode 100644
index 0000000..e26ebff
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/validation/ValidationMessages.java
@@ -0,0 +1,83 @@
+/*
+ *
+ *  * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ *  * and other contributors as indicated by the @author tags.
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  * http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.keycloak.services.validation;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+
+/**
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
+ */
+public class ValidationMessages {
+    private Set<ValidationMessage> messages = new LinkedHashSet<>();
+
+    public ValidationMessages() {}
+
+    public ValidationMessages(String... messages) {
+        for (String message : messages) {
+            add(message);
+        }
+    }
+
+    public void add(String message) {
+        messages.add(new ValidationMessage(message));
+    }
+
+    public void add(String message, String localizedMessageKey) {
+        messages.add(new ValidationMessage(message, localizedMessageKey));
+    }
+
+    public void add(String fieldId, String message, String localizedMessageKey) {
+        ValidationMessage validationMessage = new ValidationMessage(message, localizedMessageKey);
+        validationMessage.setFieldId(fieldId);
+        add(validationMessage);
+    }
+
+    public void add(ValidationMessage message) {
+        messages.add(message);
+    }
+
+    public boolean fieldHasError(String fieldId) {
+        for (ValidationMessage message : messages) {
+            if (message.getFieldId().equals(fieldId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public Set<ValidationMessage> getMessages() {
+        return Collections.unmodifiableSet(messages);
+    }
+
+    protected String getStringMessages(Function<? super ValidationMessage, ? extends String> function) {
+        return messages.stream().map(function).collect(Collectors.joining("; "));
+    }
+
+    public String getStringMessages() {
+        return getStringMessages(ValidationMessage::getMessage);
+    }
+
+    public String getStringMessages(Properties localizedMessages) {
+        return getStringMessages(x -> x.getMessage(localizedMessages));
+    }
+}
diff --git a/services/src/main/java/org/keycloak/truststore/SSLSocketFactory.java b/services/src/main/java/org/keycloak/truststore/SSLSocketFactory.java
index fd1574a..f7b5a1d 100755
--- a/services/src/main/java/org/keycloak/truststore/SSLSocketFactory.java
+++ b/services/src/main/java/org/keycloak/truststore/SSLSocketFactory.java
@@ -29,7 +29,7 @@ import java.net.Socket;
  * <p>
  * This SSLSocketFactory can only use truststore configured by TruststoreProvider after the ProviderFactory was
  * initialized using standard Spi load / init mechanism. That will only happen if "truststore" provider is configured
- * in keycloak-server.json.
+ * in standalone.xml or domain.xml.
  * <p>
  * If TruststoreProvider is not available this SSLSocketFactory will delegate all operations to javax.net.ssl.SSLSocketFactory.getDefault().
  *
diff --git a/services/src/main/java/org/keycloak/utils/MediaType.java b/services/src/main/java/org/keycloak/utils/MediaType.java
index 31ab972..c34858d 100644
--- a/services/src/main/java/org/keycloak/utils/MediaType.java
+++ b/services/src/main/java/org/keycloak/utils/MediaType.java
@@ -31,4 +31,7 @@ public class MediaType {
     public static final String APPLICATION_FORM_URLENCODED = javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
     public static final javax.ws.rs.core.MediaType APPLICATION_FORM_URLENCODED_TYPE = javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED_TYPE;
 
+    public static final String APPLICATION_JWT = "application/jwt";
+    public static final javax.ws.rs.core.MediaType APPLICATION_JWT_TYPE = new javax.ws.rs.core.MediaType("application", "jwt");
+
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractFirstBrokerLoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractFirstBrokerLoginTest.java
index 3b1b440..67b82bb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractFirstBrokerLoginTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractFirstBrokerLoginTest.java
@@ -287,6 +287,10 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractIdentityProvi
 
         // authenticated and redirected to app. User is linked with identity provider
         assertFederatedUser("pedroigor", "psilva@redhat.com", "pedroigor");
+
+        // Assert user's email is verified now
+        UserModel user = getFederatedUser();
+        Assert.assertTrue(user.isEmailVerified());
     }
 
 
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
index 3b8d68b..8806514 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
@@ -309,6 +309,8 @@ public class KeycloakServer {
             di.setDeploymentName("Keycloak");
             di.setDefaultEncoding("UTF-8");
 
+            di.addInitParameter("keycloak.embedded", "true");
+
             di.setDefaultServletConfig(new DefaultServletConfig(true));
 
             ServletInfo restEasyDispatcher = Servlets.servlet("Keycloak REST Interface", HttpServlet30Dispatcher.class);
diff --git a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
index d3f87c9..b676b99 100755
--- a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
@@ -65,7 +65,8 @@
             "driverDialect": "${keycloak.connectionsJpa.driverDialect:}",
             "user": "${keycloak.connectionsJpa.user:sa}",
             "password": "${keycloak.connectionsJpa.password:}",
-            "databaseSchema": "${keycloak.connectionsJpa.databaseSchema:update}",
+            "initializeEmpty": true,
+            "migrationStrategy": "update",
             "showSql": "${keycloak.connectionsJpa.showSql:false}",
             "formatSql": "${keycloak.connectionsJpa.formatSql:true}",
             "globalStatsInterval": "${keycloak.connectionsJpa.globalStatsInterval:-1}"
diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index 977fba8..7bada0c 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -113,12 +113,17 @@
                     <artifactId>xml-maven-plugin</artifactId>
                     <version>1.0.1</version>
                 </plugin>
+                <plugin>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>3.0.0</version>
+                </plugin>
             </plugins>
         </pluginManagement>
     </build>
     
     <modules>
         <module>test-apps</module>
+        <module>test-utils</module>
         <module>servers</module>
         <module>tests</module>
     </modules>
diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl b/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl
index e42a21c..37ce56f 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource.xsl
@@ -17,12 +17,8 @@
 
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:xalan="http://xml.apache.org/xalan"
-                xmlns:j="urn:jboss:domain:4.0"
-                xmlns:ds="urn:jboss:domain:datasources:4.0"
-                xmlns:k="urn:jboss:domain:keycloak:1.1"
-                xmlns:sec="urn:jboss:domain:security:1.2"
                 version="2.0"
-                exclude-result-prefixes="xalan j ds k sec">
+                exclude-result-prefixes="xalan">
 
     <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
     <xsl:strip-space elements="*"/>
@@ -47,7 +43,7 @@
     <xsl:param name="pool.prefill" select="'true'"/>
     
     <xsl:variable name="newDatasourceDefinition">
-        <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" use-java-context="true">
+        <datasource jndi-name="java:jboss/datasources/KeycloakDS" jta="false" pool-name="KeycloakDS" use-java-context="true">
             <connection-url>
                 <xsl:value-of select="$jdbc.url"/>
             </connection-url>
diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource-jdbc-url.xsl b/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource-jdbc-url.xsl
index 589ee4c..445b973 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource-jdbc-url.xsl
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/common/datasource-jdbc-url.xsl
@@ -1,11 +1,7 @@
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:xalan="http://xml.apache.org/xalan"
-                xmlns:j="urn:jboss:domain:4.0"
-                xmlns:ds="urn:jboss:domain:datasources:4.0"
-                xmlns:k="urn:jboss:domain:keycloak:1.1"
-                xmlns:sec="urn:jboss:domain:security:1.2"
                 version="2.0"
-                exclude-result-prefixes="xalan j ds k sec">
+                exclude-result-prefixes="xalan">
 
     <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
     <xsl:strip-space elements="*"/>
diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml b/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml
index 4fab304..eae0512 100644
--- a/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml
+++ b/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml
@@ -143,74 +143,6 @@
                         </executions>
                     </plugin>
                     <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-antrun-plugin</artifactId>
-                        <version>1.8</version>
-                        <executions>
-                            <execution>
-                                <id>inject-into-keycloak-server-json</id>
-                                <phase>process-resources</phase>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <configuration>
-                                    <target>
-                                        <ant antfile="../build.xml" inheritRefs="true">
-                                            <target name="inject-provider"/>
-                                        </ant>
-                                    </target>
-                                </configuration>
-                            </execution>
-                            <execution>
-                                <id>inject-truststore-into-keycloak-server-json</id>
-                                <phase>process-resources</phase>
-                                <goals>
-                                    <goal>run</goal>
-                                </goals>
-                                <configuration>
-                                    <target>
-                                        <ant antfile="../build-truststore.xml" inheritRefs="true">
-                                            <target name="inject-truststore"/>
-                                        </ant>
-                                    </target>
-                                </configuration>
-                            </execution>
-                        </executions>
-                        <dependencies>
-                            <dependency>
-                                <groupId>ant-contrib</groupId>
-                                <artifactId>ant-contrib</artifactId>
-                                <version>1.0b3</version>
-                                <exclusions>
-                                    <exclusion>
-                                        <groupId>ant</groupId>
-                                        <artifactId>ant</artifactId>
-                                    </exclusion>
-                                </exclusions>
-                            </dependency>
-                            <dependency>
-                                <groupId>org.apache.ant</groupId>
-                                <artifactId>ant-apache-bsf</artifactId>
-                                <version>1.9.3</version>
-                            </dependency>
-                            <dependency>
-                                <groupId>org.apache.bsf</groupId>
-                                <artifactId>bsf-api</artifactId>
-                                <version>3.1</version>
-                            </dependency>
-                            <dependency>
-                                <groupId>rhino</groupId>
-                                <artifactId>js</artifactId>
-                                <version>1.7R2</version>
-                            </dependency>
-                            <dependency>
-                                <groupId>org.keycloak</groupId>
-                                <artifactId>keycloak-core</artifactId>
-                                <version>${project.version}</version>
-                            </dependency>
-                        </dependencies>
-                    </plugin>
-                    <plugin>
                         <artifactId>maven-enforcer-plugin</artifactId>
                     </plugin>
                     <plugin>
@@ -247,6 +179,25 @@
                                     </transformationSets>
                                 </configuration>
                             </execution>
+                            <execution>
+                                <id>inject-provider-and-truststore</id>
+                                <phase>process-resources</phase>
+                                <goals>
+                                    <goal>transform</goal>
+                                </goals>
+                                <configuration>
+                                    <transformationSets>
+                                        <transformationSet>
+                                            <dir>${auth.server.home}/standalone/configuration</dir>
+                                            <includes>
+                                                <include>standalone.xml</include>
+                                            </includes>
+                                            <stylesheet>${common.resources}/keycloak-server-subsystem.xsl</stylesheet>
+                                            <outputDir>${auth.server.home}/standalone/configuration</outputDir>
+                                        </transformationSet>
+                                    </transformationSets>
+                                </configuration>
+                            </execution>
                         </executions>
                     </plugin>
                     <plugin>
@@ -318,7 +269,6 @@
             </build>
         </profile>
 
-
         <!-- OPT-IN -->
         <profile>
             <id>server-overlay</id>
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingExportImportResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingExportImportResource.java
new file mode 100644
index 0000000..4f9151c
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingExportImportResource.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.rest.resource;
+
+import java.io.File;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.keycloak.exportimport.ExportImportManager;
+import org.keycloak.models.KeycloakSession;
+
+import static org.keycloak.exportimport.ExportImportConfig.ACTION;
+import static org.keycloak.exportimport.ExportImportConfig.DEFAULT_USERS_PER_FILE;
+import static org.keycloak.exportimport.ExportImportConfig.DIR;
+import static org.keycloak.exportimport.ExportImportConfig.FILE;
+import static org.keycloak.exportimport.ExportImportConfig.PROVIDER;
+import static org.keycloak.exportimport.ExportImportConfig.REALM_NAME;
+import static org.keycloak.exportimport.ExportImportConfig.USERS_PER_FILE;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class TestingExportImportResource {
+
+    private final KeycloakSession session;
+
+    public TestingExportImportResource(KeycloakSession session) {
+        this.session = session;
+    }
+
+    @GET
+    @Path("/run-import")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response runImport() {
+        new ExportImportManager(session).runImport();
+        return Response.ok().build();
+    }
+
+    @GET
+    @Path("/run-export")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response runExport() {
+        new ExportImportManager(session).runExport();
+        return Response.ok().build();
+    }
+
+    @GET
+    @Path("/get-users-per-file")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Integer getUsersPerFile() {
+        String usersPerFile = System.getProperty(USERS_PER_FILE, String.valueOf(DEFAULT_USERS_PER_FILE));
+        return Integer.parseInt(usersPerFile.trim());
+    }
+
+    @PUT
+    @Path("/set-users-per-file")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setUsersPerFile(@QueryParam("usersPerFile") Integer usersPerFile) {
+        System.setProperty(USERS_PER_FILE, String.valueOf(usersPerFile));
+    }
+
+    @GET
+    @Path("/get-dir")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getDir() {
+        return System.getProperty(DIR);
+    }
+
+    @PUT
+    @Path("/set-dir")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String setDir(@QueryParam("dir") String dir) {
+        return System.setProperty(DIR, dir);
+    }
+
+    @PUT
+    @Path("/export-import-provider")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setProvider(@QueryParam("exportImportProvider") String exportImportProvider) {
+        System.setProperty(PROVIDER, exportImportProvider);
+    }
+
+    @PUT
+    @Path("/export-import-file")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setFile(@QueryParam("file") String file) {
+        System.setProperty(FILE, file);
+    }
+
+    @PUT
+    @Path("/export-import-action")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setAction(@QueryParam("exportImportAction") String exportImportAction) {
+        System.setProperty(ACTION, exportImportAction);
+    }
+
+    @PUT
+    @Path("/set-realm-name")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setRealmName(@QueryParam("realmName") String realmName) {
+        if (realmName != null && !realmName.isEmpty()) {
+            System.setProperty(REALM_NAME, realmName);
+        } else {
+            System.getProperties().remove(REALM_NAME);
+        }
+    }
+
+    @GET
+    @Path("/get-test-dir")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getExportImportTestDirectory() {
+        System.setProperty("project.build.directory", "target");
+        String absolutePath = new File(System.getProperty("project.build.directory", "target")).getAbsolutePath();
+        return absolutePath;
+    }
+}
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java
new file mode 100644
index 0000000..6ea488f
--- /dev/null
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/resource/TestingOIDCEndpointsApplicationResource.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.rest.resource;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.jboss.resteasy.spi.BadRequestException;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.jose.jwk.JSONWebKeySet;
+import org.keycloak.jose.jwk.JWK;
+import org.keycloak.jose.jwk.JWKBuilder;
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.jose.jws.JWSBuilder;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.testsuite.rest.TestApplicationResourceProviderFactory;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class TestingOIDCEndpointsApplicationResource {
+
+    public static final String PRIVATE_KEY = "privateKey";
+    public static final String PUBLIC_KEY = "publicKey";
+
+    private final TestApplicationResourceProviderFactory.OIDCClientData clientData;
+
+    public TestingOIDCEndpointsApplicationResource(TestApplicationResourceProviderFactory.OIDCClientData oidcClientData) {
+        this.clientData = oidcClientData;
+    }
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/generate-keys")
+    @NoCache
+    public Map<String, String> generateKeys() {
+        try {
+            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
+            generator.initialize(2048);
+            clientData.setSigningKeyPair(generator.generateKeyPair());
+        } catch (NoSuchAlgorithmException e) {
+            throw new BadRequestException("Error generating signing keypair", e);
+        }
+
+        String privateKeyPem = KeycloakModelUtils.getPemFromKey(clientData.getSigningKeyPair().getPrivate());
+        String publicKeyPem = KeycloakModelUtils.getPemFromKey(clientData.getSigningKeyPair().getPublic());
+
+        Map<String, String> res = new HashMap<>();
+        res.put(PRIVATE_KEY, privateKeyPem);
+        res.put(PUBLIC_KEY, publicKeyPem);
+        return res;
+    }
+
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/get-jwks")
+    @NoCache
+    public JSONWebKeySet getJwks() {
+        JSONWebKeySet keySet = new JSONWebKeySet();
+
+        if (clientData.getSigningKeyPair() == null) {
+            keySet.setKeys(new JWK[] {});
+        } else {
+            keySet.setKeys(new JWK[] { JWKBuilder.create().rs256(clientData.getSigningKeyPair().getPublic()) });
+        }
+
+        return keySet;
+    }
+
+
+    @GET
+    @Path("/set-oidc-request")
+    @Produces(org.keycloak.utils.MediaType.APPLICATION_JWT)
+    @NoCache
+    public void setOIDCRequest(@QueryParam("realmName") String realmName, @QueryParam("clientId") String clientId,
+                               @QueryParam("redirectUri") String redirectUri, @QueryParam("maxAge") String maxAge,
+                               @QueryParam("jwaAlgorithm") String jwaAlgorithm) {
+        Map<String, Object> oidcRequest = new HashMap<>();
+        oidcRequest.put(OIDCLoginProtocol.CLIENT_ID_PARAM, clientId);
+        oidcRequest.put(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, OAuth2Constants.CODE);
+        oidcRequest.put(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri);
+        if (maxAge != null) {
+            oidcRequest.put(OIDCLoginProtocol.MAX_AGE_PARAM, Integer.parseInt(maxAge));
+        }
+
+        Algorithm alg = Enum.valueOf(Algorithm.class, jwaAlgorithm);
+        if (alg == Algorithm.none) {
+            clientData.setOidcRequest(new JWSBuilder().jsonContent(oidcRequest).none());
+        } else if (alg == Algorithm.RS256) {
+            if (clientData.getSigningKeyPair() == null) {
+                throw new BadRequestException("Requested RS256, but signing key not set");
+            }
+
+            PrivateKey privateKey = clientData.getSigningKeyPair().getPrivate();
+            clientData.setOidcRequest(new JWSBuilder().jsonContent(oidcRequest).rsa256(privateKey));
+        } else {
+            throw new BadRequestException("Unknown argument: " + jwaAlgorithm);
+        }
+    }
+
+
+    @GET
+    @Path("/get-oidc-request")
+    @Produces(org.keycloak.utils.MediaType.APPLICATION_JWT)
+    @NoCache
+    public String getOIDCRequest() {
+        return clientData.getOidcRequest();
+    }
+}
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java
index bc63c99..5f392a0 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java
@@ -27,6 +27,8 @@ import org.keycloak.representations.adapters.action.PushNotBeforeAction;
 import org.keycloak.representations.adapters.action.TestAvailabilityAction;
 import org.keycloak.services.resource.RealmResourceProvider;
 import org.keycloak.services.resources.RealmsResource;
+import org.keycloak.testsuite.rest.resource.TestingExportImportResource;
+import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
@@ -53,14 +55,16 @@ public class TestApplicationResourceProvider implements RealmResourceProvider {
     private final BlockingQueue<LogoutAction> adminLogoutActions;
     private final BlockingQueue<PushNotBeforeAction> adminPushNotBeforeActions;
     private final BlockingQueue<TestAvailabilityAction> adminTestAvailabilityAction;
+    private final TestApplicationResourceProviderFactory.OIDCClientData oidcClientData;
 
     public TestApplicationResourceProvider(KeycloakSession session, BlockingQueue<LogoutAction> adminLogoutActions,
             BlockingQueue<PushNotBeforeAction> adminPushNotBeforeActions,
-            BlockingQueue<TestAvailabilityAction> adminTestAvailabilityAction) {
+            BlockingQueue<TestAvailabilityAction> adminTestAvailabilityAction, TestApplicationResourceProviderFactory.OIDCClientData oidcClientData) {
         this.session = session;
         this.adminLogoutActions = adminLogoutActions;
         this.adminPushNotBeforeActions = adminPushNotBeforeActions;
         this.adminTestAvailabilityAction = adminTestAvailabilityAction;
+        this.oidcClientData = oidcClientData;
     }
 
     @POST
@@ -164,6 +168,11 @@ public class TestApplicationResourceProvider implements RealmResourceProvider {
         return sb.toString();
     }
 
+    @Path("/oidc-client-endpoints")
+    public TestingOIDCEndpointsApplicationResource getTestingOIDCClientEndpoints() {
+        return new TestingOIDCEndpointsApplicationResource(oidcClientData);
+    }
+
     @Override
     public Object getResource() {
         return this;
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java
index 98ca2ba..6bd7dc2 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java
@@ -28,6 +28,7 @@ import org.keycloak.representations.adapters.action.TestAvailabilityAction;
 import org.keycloak.services.resource.RealmResourceProvider;
 import org.keycloak.services.resource.RealmResourceProviderFactory;
 
+import java.security.KeyPair;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingDeque;
 
@@ -40,9 +41,11 @@ public class TestApplicationResourceProviderFactory implements RealmResourceProv
     private BlockingQueue<PushNotBeforeAction> pushNotBeforeActions = new LinkedBlockingDeque<>();
     private BlockingQueue<TestAvailabilityAction> testAvailabilityActions = new LinkedBlockingDeque<>();
 
+    private final OIDCClientData oidcClientData = new OIDCClientData();
+
     @Override
     public RealmResourceProvider create(KeycloakSession session) {
-        return new TestApplicationResourceProvider(session, adminLogoutActions, pushNotBeforeActions, testAvailabilityActions);
+        return new TestApplicationResourceProvider(session, adminLogoutActions, pushNotBeforeActions, testAvailabilityActions, oidcClientData);
     }
 
     @Override
@@ -62,4 +65,26 @@ public class TestApplicationResourceProviderFactory implements RealmResourceProv
         return "app";
     }
 
+
+    public static class OIDCClientData {
+
+        private KeyPair signingKeyPair;
+        private String oidcRequest;
+
+        public KeyPair getSigningKeyPair() {
+            return signingKeyPair;
+        }
+
+        public void setSigningKeyPair(KeyPair signingKeyPair) {
+            this.signingKeyPair = signingKeyPair;
+        }
+
+        public String getOidcRequest() {
+            return oidcRequest;
+        }
+
+        public void setOidcRequest(String oidcRequest) {
+            this.oidcRequest = oidcRequest;
+        }
+    }
 }
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
index b658d35..2085cfa 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
@@ -23,15 +23,20 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import org.infinispan.Cache;
+import org.keycloak.OAuth2Constants;
 import org.keycloak.common.util.Time;
 import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
 import org.keycloak.events.Event;
 import org.keycloak.events.admin.AdminEvent;
 import org.keycloak.events.admin.ResourceType;
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.jose.jws.JWSBuilder;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserSessionModel;
 import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.endpoints.request.AuthorizationEndpointRequest;
 import org.keycloak.representations.idm.AdminEventRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.services.managers.ClientSessionCode;
@@ -76,6 +81,7 @@ import org.keycloak.models.UserProvider;
 import org.keycloak.representations.idm.AuthDetailsRepresentation;
 import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.rest.resource.TestingExportImportResource;
 
 import static org.keycloak.exportimport.ExportImportConfig.*;
 
@@ -565,22 +571,6 @@ public class TestingResourceProvider implements RealmResourceProvider {
     }
 
     @GET
-    @Path("/run-import")
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response runImport() {
-        new ExportImportManager(session).runImport();
-        return Response.ok().build();
-    }
-
-    @GET
-    @Path("/run-export")
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response runExport() {
-        new ExportImportManager(session).runExport();
-        return Response.ok().build();
-    }
-
-    @GET
     @Path("/valid-credentials")
     @Produces(MediaType.APPLICATION_JSON)
     public boolean validCredentials(@QueryParam("realmName") String realmName, @QueryParam("userName") String userName, @QueryParam("password") String password) {
@@ -647,83 +637,14 @@ public class TestingResourceProvider implements RealmResourceProvider {
         return ModelToRepresentation.toRepresentation(user);
     }
 
+    @Path("/export-import")
+    public TestingExportImportResource getExportImportResource() {
+        return new TestingExportImportResource(session);
+    }
+
     private RealmModel getRealmByName(String realmName) {
         RealmProvider realmProvider = session.getProvider(RealmProvider.class);
         return realmProvider.getRealmByName(realmName);
     }
 
-    @GET
-    @Path("/get-users-per-file")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Integer getUsersPerFile() {
-        String usersPerFile = System.getProperty(USERS_PER_FILE, String.valueOf(DEFAULT_USERS_PER_FILE));
-        return Integer.parseInt(usersPerFile.trim());
-    }
-
-    @PUT
-    @Path("/set-users-per-file")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setUsersPerFile(@QueryParam("usersPerFile") Integer usersPerFile) {
-        System.setProperty(USERS_PER_FILE, String.valueOf(usersPerFile));
-    }
-
-    @GET
-    @Path("/get-dir")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public String getDir() {
-        return System.getProperty(DIR);
-    }
-
-    @PUT
-    @Path("/set-dir")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public String setDir(@QueryParam("dir") String dir) {
-        return System.setProperty(DIR, dir);
-    }
-
-    @PUT
-    @Path("/export-import-provider")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setProvider(@QueryParam("exportImportProvider") String exportImportProvider) {
-        System.setProperty(PROVIDER, exportImportProvider);
-    }
-
-    @PUT
-    @Path("/export-import-file")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setFile(@QueryParam("file") String file) {
-        System.setProperty(FILE, file);
-    }
-
-    @PUT
-    @Path("/export-import-action")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setAction(@QueryParam("exportImportAction") String exportImportAction) {
-        System.setProperty(ACTION, exportImportAction);
-    }
-
-    @PUT
-    @Path("/set-realm-name")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setRealmName(@QueryParam("realmName") String realmName) {
-        if (realmName != null && !realmName.isEmpty()) {
-            System.setProperty(REALM_NAME, realmName);
-        } else {
-            System.getProperties().remove(REALM_NAME);
-        }
-    }
-
-    @GET
-    @Path("/get-test-dir")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public String getExportImportTestDirectory() {
-        System.setProperty("project.build.directory", "target");
-        String absolutePath = new File(System.getProperty("project.build.directory", "target")).getAbsolutePath();
-        return absolutePath;
-    }
-
 }
diff --git a/testsuite/integration-arquillian/servers/migration/pom.xml b/testsuite/integration-arquillian/servers/migration/pom.xml
index 6f6301a..b7a5ff9 100644
--- a/testsuite/integration-arquillian/servers/migration/pom.xml
+++ b/testsuite/integration-arquillian/servers/migration/pom.xml
@@ -1,20 +1,20 @@
 <?xml version="1.0"?>
 <!--
-  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
-  ~ and other contributors as indicated by the @author tags.
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
 
 <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
@@ -25,231 +25,195 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>integration-arquillian-migration-servers</artifactId>
+    <artifactId>integration-arquillian-migration-server</artifactId>
     <packaging>pom</packaging>
-    <name>Migration Servers</name>
+    <name>Migration Server</name>
+
+    <properties>
+        <keycloak.server.home>${project.build.directory}/unpacked/keycloak-${migrated.auth.server.version}</keycloak.server.home>
+        <jdbc.mvn.driver.deployment.dir>${keycloak.server.home}/modules/system/layers/base/com/${jdbc.mvn.artifactId}/main</jdbc.mvn.driver.deployment.dir>
+    </properties>
 
-    <profiles>
-        <profile>
-            <id>migration-kc16</id>
-            <modules>
-                <module>wildfly_kc16</module>
-            </modules>
-        </profile>
-        <profile>
-            <id>migration-kc15</id>
-            <modules>
-                <module>wildfly_kc15</module>
-            </modules>
-        </profile>
-        <profile>
-            <id>migration-kc14</id>
-            <modules>
-                <module>wildfly_kc14</module>
-            </modules>
-        </profile>
-        <profile>
-            <id>migration-kc13</id>
-            <modules>
-                <module>wildfly_kc13</module>
-            </modules>
-        </profile>
-        <profile>
-            <id>migration-kc12</id>
-            <modules>
-                <module>wildfly_kc12</module>
-            </modules>
-        </profile>
-    </profiles>   
-    
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-enforcer-plugin</artifactId>
+                <artifactId>maven-deploy-plugin</artifactId>
                 <configuration>
                     <skip>true</skip>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>enforce-properties</id>
+                        <goals>
+                            <goal>enforce</goal>
+                        </goals>
+                        <configuration>
+                            <rules>
+                                <requireProperty>
+                                    <property>migrated.auth.server.version</property>
+                                </requireProperty>
+                                <requireProperty>
+                                    <property>jdbc.mvn.groupId</property>
+                                </requireProperty>
+                                <requireProperty>
+                                    <property>jdbc.mvn.artifactId</property>
+                                </requireProperty>
+                                <requireProperty>
+                                    <property>jdbc.mvn.version</property>
+                                </requireProperty>
+                                <requireProperty>
+                                    <property>keycloak.connectionsJpa.url</property>
+                                </requireProperty>
+                                <requireProperty>
+                                    <property>keycloak.connectionsJpa.user</property>
+                                </requireProperty>
+                                <requireProperty>
+                                    <property>keycloak.connectionsJpa.password</property>
+                                </requireProperty>
+                            </rules>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>unpack-server</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-server-dist</artifactId>
+                                    <version>${migrated.auth.server.version}</version>
+                                    <type>zip</type>
+                                    <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>jdbc-driver</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>${jdbc.mvn.groupId}</groupId>
+                                    <artifactId>${jdbc.mvn.artifactId}</artifactId>
+                                    <version>${jdbc.mvn.version}</version>
+                                    <type>jar</type>
+                                </artifactItem>
+                            </artifactItems>
+                            <outputDirectory>${jdbc.mvn.driver.deployment.dir}</outputDirectory>
+                            <overWriteIfNewer>true</overWriteIfNewer>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>xml-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>configure-wildfly-datasource</id>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>transform</goal>
+                        </goals>
+                        <configuration>
+                            <transformationSets>
+                                <!-- create module.xml in modules -->
+                                <transformationSet>
+                                    <dir>${keycloak.server.home}/modules/system/layers/base/com/h2database/h2/main</dir>
+                                    <stylesheet>src/main/xslt/module.xsl</stylesheet>
+                                    <includes>
+                                        <include>module.xml</include>
+                                    </includes>
+                                    <outputDir>${jdbc.mvn.driver.deployment.dir}</outputDir>
+                                    <parameters>
+                                        <parameter>
+                                            <name>database</name>
+                                            <value>${jdbc.mvn.artifactId}</value>
+                                        </parameter>
+                                        <parameter>
+                                            <name>version</name>
+                                            <value>${jdbc.mvn.version}</value>
+                                        </parameter>
+                                    </parameters>
+                                </transformationSet>
+                                <!-- add datasource to standalone.xml -->
+                                <transformationSet>
+                                    <dir>${keycloak.server.home}/standalone/configuration</dir>
+                                    <stylesheet>src/main/xslt/datasource.xsl</stylesheet>
+                                    <includes>
+                                        <include>standalone.xml</include>
+                                    </includes>
+                                    <outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
+                                    <parameters>
+                                        <parameter>
+                                            <name>jdbc.url</name>
+                                            <value>${keycloak.connectionsJpa.url}</value>
+                                        </parameter>
+                                        <parameter>
+                                            <name>driver</name>
+                                            <value>${jdbc.mvn.artifactId}</value>
+                                        </parameter>
+                                        <parameter>
+                                            <name>username</name>
+                                            <value>${keycloak.connectionsJpa.user}</value>
+                                        </parameter>
+                                        <parameter>
+                                            <name>password</name>
+                                            <value>${keycloak.connectionsJpa.password}</value>
+                                        </parameter>
+                                    </parameters>
+                                </transformationSet>
+                                <!-- add logger for org.hibernate.dialect.Dialect to standalone.xml-->
+                                <transformationSet>
+                                    <dir>${keycloak.server.home}/standalone/configuration</dir>
+                                    <stylesheet>src/main/xslt/add-dialect-logger.xsl</stylesheet>
+                                    <includes>
+                                        <include>standalone.xml</include>
+                                    </includes>
+                                    <outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
+                                </transformationSet>
+                            </transformationSets>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>create-zip</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly.xml</descriptor>
+                            </descriptors>
+                            <appendAssemblyId>false</appendAssemblyId>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
-        <pluginManagement>
-            <plugins>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-deploy-plugin</artifactId>
-                    <configuration>
-                        <skip>true</skip>
-                    </configuration>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-enforcer-plugin</artifactId>
-                    <executions>
-                        <execution>
-                            <id>enforce-properties</id>
-                            <goals>
-                                <goal>enforce</goal>
-                            </goals>
-                            <configuration>
-                                <rules>
-                                    <requireProperty>
-                                        <property>jdbc.mvn.groupId</property>
-                                    </requireProperty>
-                                    <requireProperty>
-                                        <property>jdbc.mvn.artifactId</property>
-                                    </requireProperty>
-                                    <requireProperty>
-                                        <property>jdbc.mvn.version</property>
-                                    </requireProperty>
-                                    <requireProperty>
-                                        <property>keycloak.connectionsJpa.url</property>
-                                    </requireProperty>
-                                    <requireProperty>
-                                        <property>keycloak.connectionsJpa.user</property>
-                                    </requireProperty>
-                                    <requireProperty>
-                                        <property>keycloak.connectionsJpa.password</property>
-                                    </requireProperty>
-                                </rules>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-dependency-plugin</artifactId>
-                    <executions>
-                        <execution>
-                            <id>unpack-server</id>
-                            <phase>generate-resources</phase>
-                            <goals>
-                                <goal>unpack</goal>
-                            </goals>
-                            <configuration>
-                                <artifactItems>
-                                    <artifactItem>
-                                        <groupId>org.keycloak</groupId>
-                                        <artifactId>keycloak-server-dist</artifactId>
-                                        <version>${server.version}</version>
-                                        <type>zip</type>
-                                        <outputDirectory>${project.build.directory}/unpacked</outputDirectory>
-                                    </artifactItem>
-                                </artifactItems>
-                            </configuration>
-                        </execution>
-                        <execution>
-                            <id>jdbc-driver</id>
-                            <phase>process-resources</phase>
-                            <goals>
-                                <goal>copy</goal>
-                            </goals>
-                            <configuration>
-                                <artifactItems>
-                                    <artifactItem>
-                                        <groupId>${jdbc.mvn.groupId}</groupId>
-                                        <artifactId>${jdbc.mvn.artifactId}</artifactId>
-                                        <version>${jdbc.mvn.version}</version>
-                                        <type>jar</type>
-                                    </artifactItem>
-                                </artifactItems>
-                                <outputDirectory>${jdbc.mvn.driver.deployment.dir}</outputDirectory>
-                                <overWriteIfNewer>true</overWriteIfNewer>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <groupId>org.codehaus.mojo</groupId>
-                    <artifactId>xml-maven-plugin</artifactId>
-                    <executions>
-                        <execution>
-                            <id>configure-wildfly-datasource</id>
-                            <phase>process-resources</phase>
-                            <goals>
-                                <goal>transform</goal>
-                            </goals>
-                            <configuration>
-                                <transformationSets>
-                                    <!-- create module.xml in modules -->
-                                    <transformationSet>
-                                        <dir>${keycloak.server.home}/modules/system/layers/base/com/h2database/h2/main</dir>
-                                        <stylesheet>src/main/xslt/module.xsl</stylesheet>
-                                        <includes>
-                                            <include>module.xml</include>
-                                        </includes>
-                                        <outputDir>${jdbc.mvn.driver.deployment.dir}</outputDir>
-                                        <parameters>
-                                            <parameter>
-                                                <name>database</name>
-                                                <value>${jdbc.mvn.artifactId}</value>
-                                            </parameter>
-                                            <parameter>
-                                                <name>version</name>
-                                                <value>${jdbc.mvn.version}</value>
-                                            </parameter>
-                                        </parameters>
-                                    </transformationSet>
-                                    <!-- add datasource to standalone.xml -->
-                                    <transformationSet>
-                                        <dir>${keycloak.server.home}/standalone/configuration</dir>
-                                        <stylesheet>src/main/xslt/datasource.xsl</stylesheet>
-                                        <includes>
-                                            <include>standalone.xml</include>
-                                        </includes>
-                                        <outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
-                                        <parameters>
-                                            <parameter>
-                                                <name>jdbc.url</name>
-                                                <value>${keycloak.connectionsJpa.url}</value>
-                                            </parameter>
-                                            <parameter>
-                                                <name>driver</name>
-                                                <value>${jdbc.mvn.artifactId}</value>
-                                            </parameter>
-                                            <parameter>
-                                                <name>username</name>
-                                                <value>${keycloak.connectionsJpa.user}</value>
-                                            </parameter>
-                                            <parameter>
-                                                <name>password</name>
-                                                <value>${keycloak.connectionsJpa.password}</value>
-                                            </parameter>
-                                        </parameters>
-                                    </transformationSet>
-                                    <!-- add logger for org.hibernate.dialect.Dialect to standalone.xml-->
-                                    <transformationSet>
-                                        <dir>${keycloak.server.home}/standalone/configuration</dir>
-                                        <stylesheet>src/main/xslt/add-dialect-logger.xsl</stylesheet>
-                                        <includes>
-                                            <include>standalone.xml</include>
-                                        </includes>
-                                        <outputDir>${keycloak.server.home}/standalone/configuration</outputDir>
-                                    </transformationSet>
-                                </transformationSets>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <groupId>org.apache.maven.plugins</groupId>
-                    <artifactId>maven-assembly-plugin</artifactId>
-                    <executions>
-                        <execution>
-                            <id>create-zip</id>
-                            <phase>package</phase>
-                            <goals>
-                                <goal>single</goal>
-                            </goals>
-                            <configuration>
-                                <descriptors>
-                                    <descriptor>assembly.xml</descriptor>
-                                </descriptors>
-                                <appendAssemblyId>false</appendAssemblyId>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-            </plugins>
-        </pluginManagement>
     </build>
 </project>
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml
index 7885857..f5e2d4c 100755
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml
@@ -40,6 +40,12 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>1.0-SP4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-authz-client</artifactId>
             <version>${project.version}</version>
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java
index b349e02..428ba07 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/admin/AdminAlbumService.java
@@ -19,9 +19,8 @@ package org.keycloak.example.photoz.admin;
 
 import org.keycloak.example.photoz.entity.Album;
 
-import javax.ejb.Stateless;
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -36,12 +35,11 @@ import java.util.List;
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 @Path("/admin/album")
-@Stateless
 public class AdminAlbumService {
 
     public static final String SCOPE_ADMIN_ALBUM_MANAGE = "urn:photoz.com:scopes:album:admin:manage";
 
-    @PersistenceContext
+    @Inject
     private EntityManager entityManager;
 
     @Context
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java
index a5d7f16..d0e9c2d 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/AlbumService.java
@@ -7,10 +7,12 @@ import org.keycloak.authorization.client.representation.ScopeRepresentation;
 import org.keycloak.authorization.client.resource.ProtectionResource;
 import org.keycloak.example.photoz.ErrorResponse;
 import org.keycloak.example.photoz.entity.Album;
+import org.keycloak.example.photoz.util.Transaction;
 import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.util.JsonSerialization;
 
 import javax.ejb.Stateless;
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
@@ -31,14 +33,14 @@ import java.util.List;
 import java.util.Set;
 
 @Path("/album")
-@Stateless
+@Transaction
 public class AlbumService {
 
     public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view";
     public static final String SCOPE_ALBUM_CREATE = "urn:photoz.com:scopes:album:create";
     public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete";
 
-    @PersistenceContext
+    @Inject
     private EntityManager entityManager;
 
     @Context
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java
index be638b6..f7b55cb 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/album/ProfileService.java
@@ -18,6 +18,7 @@
 package org.keycloak.example.photoz.album;
 
 import javax.ejb.Stateless;
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.servlet.http.HttpServletRequest;
@@ -34,12 +35,11 @@ import java.util.List;
  * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
  */
 @Path("/profile")
-@Stateless
 public class ProfileService {
 
     private static final String PROFILE_VIEW = "urn:photoz.com:scopes:profile:view";
 
-    @PersistenceContext
+    @Inject
     private EntityManager entityManager;
 
     @GET
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java
new file mode 100644
index 0000000..c917da2
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Resources.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.photoz.util;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.inject.Produces;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@ApplicationScoped
+public class Resources {
+
+    private EntityManagerFactory entityManagerFactory;
+
+    @PostConstruct
+    public void init() {
+        entityManagerFactory = Persistence.createEntityManagerFactory("primary");
+    }
+
+    @PreDestroy
+    public void dispose() {
+        entityManagerFactory.close();
+    }
+
+    @RequestScoped
+    @Produces
+    public EntityManager createEntityManager() {
+        return entityManagerFactory.createEntityManager();
+    }
+}
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java
new file mode 100644
index 0000000..a3caa78
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/Transaction.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.photoz.util;
+
+import javax.interceptor.InterceptorBinding;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@InterceptorBinding
+@Target({ TYPE })
+@Retention(RUNTIME)
+public @interface Transaction {
+}
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java
new file mode 100644
index 0000000..36d35f3
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.photoz.util;
+
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+@Interceptor
+@Transaction
+public class TransactionInterceptor {
+
+    @Inject
+    private Instance<EntityManager> entityManager;
+
+    @AroundInvoke
+    public Object aroundInvoke(InvocationContext context) {
+        EntityManager entityManager = this.entityManager.get();
+        EntityTransaction transaction = entityManager.getTransaction();
+
+        try {
+            transaction.begin();
+            Object proceed = context.proceed();
+            transaction.commit();
+            return proceed;
+        } catch (Exception cause) {
+            if (transaction != null && transaction.isActive()) {
+                transaction.rollback();
+            }
+            throw new RuntimeException(cause);
+        } finally {
+            entityManager.close();
+        }
+    }
+}
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml
index 957dc8a..fbf2a32 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/beans.xml
@@ -3,5 +3,7 @@
    xsi:schemaLocation="
         http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
-        
+    <interceptors>
+        <class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
+    </interceptors>
 </beans>
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml
index 9323182..8b6d226 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/resources/META-INF/persistence.xml
@@ -4,14 +4,18 @@
 	xsi:schemaLocation="
         http://java.sun.com/xml/ns/persistence
         http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
-	<persistence-unit name="primary">
-		<non-jta-data-source>java:jboss/datasources/PhotozDS</non-jta-data-source>
+	<persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
 
 		<class>org.keycloak.example.photoz.entity.Album</class>
 		<class>org.keycloak.example.photoz.entity.Photo</class>
 
 		<properties>
-			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+			<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
+			<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
+			<property name="hibernate.connection.url" value="jdbc:h2:mem:test-keycloak-photoz-example" />
+			<property name="hibernate.connection.user" value="sa" />
+			<property name="hibernate.flushMode" value="FLUSH_AUTO" />
 			<property name="hibernate.hbm2ddl.auto" value="update" />
 			<property name="hibernate.show_sql" value="false" />
 		</properties>
diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml
index 4b23be6..4553358 100644
--- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml
+++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/src/main/webapp/META-INF/jboss-deployment-structure.xml
@@ -20,6 +20,7 @@
     <deployment>
         <dependencies>
             <module name="org.keycloak.keycloak-authz-client" services="import"/>
+            <module name="com.h2database.h2" services="import"/>
         </dependencies>
     </deployment>
 </jboss-deployment-structure>
diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml
index ac85ebd..15594da 100644
--- a/testsuite/integration-arquillian/tests/base/pom.xml
+++ b/testsuite/integration-arquillian/tests/base/pom.xml
@@ -36,8 +36,6 @@
         <exclude.console>-</exclude.console>
         <exclude.account>-</exclude.account>
         <exclude.client>-</exclude.client>
-        <!--exclude migration tests by default, enabled by 'migration' profile in tests/pom.xml-->
-        <exclude.migration>**/migration/**/*Test.java</exclude.migration>
         <!--exclude cluster tests by default, enabled by 'auth-server-*-cluster' profiles in tests/pom.xml-->
         <exclude.cluster>**/cluster/**/*Test.java</exclude.cluster>
     </properties>
@@ -102,7 +100,6 @@
                         <exclude>${exclude.console}</exclude>
                         <exclude>${exclude.account}</exclude>
                         <exclude>${exclude.client}</exclude>
-                        <exclude>${exclude.migration}</exclude>
                         <exclude>${exclude.cluster}</exclude>
                     </excludes>
                 </configuration>
@@ -137,6 +134,7 @@
                             <goal>copy-resources</goal>
                         </goals>
                         <configuration>
+                            <skip>${skip.add.user.json}</skip>
                             <outputDirectory>${auth.server.config.dir}</outputDirectory>
                             <resources>
                                 <resource>
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BadAssertionSalesPostSig.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BadAssertionSalesPostSig.java
new file mode 100644
index 0000000..8d10b22
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/BadAssertionSalesPostSig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.page;
+
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+
+/**
+ * @author mhajas
+ */
+public class BadAssertionSalesPostSig extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "bad-assertion-sales-post-sig";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        return url;
+    }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/EmployeeServlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/EmployeeServlet.java
new file mode 100644
index 0000000..c8a0d66
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/EmployeeServlet.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.page;
+
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+
+/**
+ * @author mhajas
+ */
+public class EmployeeServlet extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "employee";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        return url;
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/InputPortal.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/InputPortal.java
index 6e66e2c..7edc5c5 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/InputPortal.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/InputPortal.java
@@ -17,18 +17,18 @@
 
 package org.keycloak.testsuite.adapter.page;
 
-import java.net.URL;
 import org.jboss.arquillian.container.test.api.OperateOnDeployment;
 import org.jboss.arquillian.test.api.ArquillianResource;
-import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
 
+import java.net.URL;
+
 /**
  *
  * @author tkyjovsk
  */
-public class InputPortal extends AbstractPageWithInjectedUrl {
+public class InputPortal extends SAMLServlet {
 
     public static final String DEPLOYMENT_NAME = "input-portal";
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MissingAssertionSig.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MissingAssertionSig.java
new file mode 100644
index 0000000..78ff38c
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/MissingAssertionSig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.page;
+
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+
+/**
+ * @author mhajas
+ */
+public class MissingAssertionSig extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "missing-assertion-sig";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        return url;
+    }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SalesPost2Servlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SalesPost2Servlet.java
new file mode 100644
index 0000000..d821d86
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SalesPost2Servlet.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.page;
+
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+
+/**
+ * @author mhajas
+ */
+public class SalesPost2Servlet extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "sales-post2";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        return url;
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SalesPostAssertionAndResponseSig.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SalesPostAssertionAndResponseSig.java
new file mode 100644
index 0000000..a4522b4
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SalesPostAssertionAndResponseSig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.page;
+
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.test.api.ArquillianResource;
+
+import java.net.URL;
+
+/**
+ * @author mhajas
+ */
+public class SalesPostAssertionAndResponseSig extends SAMLServlet {
+    public static final String DEPLOYMENT_NAME = "sales-post-assertion-and-response-sig";
+
+    @ArquillianResource
+    @OperateOnDeployment(DEPLOYMENT_NAME)
+    private URL url;
+
+    @Override
+    public URL getInjectedUrl() {
+        return url;
+    }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java
index fe856dc..cc4a419 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/SAMLServlet.java
@@ -40,8 +40,8 @@ public abstract class SAMLServlet extends AbstractPageWithInjectedUrl {
         }
     }
 
-    public void checkRolesEndPoint() {
-        driver.navigate().to(getUriBuilder().build().toASCIIString() + "/checkRoles");
+    public void checkRolesEndPoint(boolean value) {
+        driver.navigate().to(getUriBuilder().build().toASCIIString() + "/" + (value ? "" : "un") + "checkRoles");
         pause(300);
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/InputServlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/InputServlet.java
index a2038bf..5fb04e9 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/InputServlet.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/InputServlet.java
@@ -17,6 +17,8 @@
 
 package org.keycloak.testsuite.adapter.servlet;
 
+import org.junit.Assert;
+
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
@@ -31,6 +33,8 @@ import java.io.PrintWriter;
 @WebServlet("/input-portal")
 public class InputServlet extends HttpServlet {
 
+    private static final String FORM_URLENCODED = "application/x-www-form-urlencoded";
+
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         String appBase;
@@ -41,6 +45,16 @@ public class InputServlet extends HttpServlet {
         }
         String actionUrl = appBase + "/input-portal/secured/post";
 
+        if (req.getRequestURI().endsWith("insecure")) {
+            if (System.getProperty("insecure.user.principal.unsupported") == null) Assert.assertNotNull(req.getUserPrincipal());
+            resp.setContentType("text/html");
+            PrintWriter pw = resp.getWriter();
+            pw.printf("<html><head><title>Input Servlet</title></head><body>%s\n", "Insecure Page");
+            if (req.getUserPrincipal() != null) pw.printf("UserPrincipal: " + req.getUserPrincipal().getName());
+            pw.print("</body></html>");
+            pw.flush();
+            return;
+        }
 
         resp.setContentType("text/html");
         PrintWriter pw = resp.getWriter();
@@ -56,6 +70,16 @@ public class InputServlet extends HttpServlet {
 
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        if (!FORM_URLENCODED.equals(req.getContentType())) {
+            resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+            PrintWriter pw = resp.getWriter();
+            resp.setContentType("text/plain");
+            pw.printf("Expecting content type " + FORM_URLENCODED +
+                    ", received " + req.getContentType() + " instead");
+            pw.flush();
+            return;
+        }
+
         resp.setContentType("text/plain");
         PrintWriter pw = resp.getWriter();
         pw.printf("parameter="+req.getParameter("parameter"));
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlSPFacade.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlSPFacade.java
new file mode 100755
index 0000000..21f07b3
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SamlSPFacade.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.adapter.servlet;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.UriBuilder;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+* @version $Revision: 1 $
+*/
+public class SamlSPFacade extends HttpServlet {
+    public static String samlResponse;
+    public static String RELAY_STATE = "http://test.com/foo/bar";
+    public static String sentRelayState;
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        handler(req, resp);
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        handler(req, resp);
+    }
+
+    private void handler(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        System.out.println("In SamlSPFacade Servlet handler()");
+        if (req.getParameterMap().isEmpty()) {
+            System.out.println("ParameterMap is empty, redirecting to keycloak server ");
+            resp.setStatus(302);
+            // Redirect
+            // UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVLRTsIwFP2Vpe%2BjG4wxG0YyWYxL0BBAH3wx3XYnTbp29nYof%2B8YEvEBNOlD03vOveec2ynyWjYsae1WreC9BbTOZy0Vsr4Qk9YopjkKZIrXgMwWbJ08LNhw4LHGaKsLLcmRch3MEcFYoRVxktN1rhW2NZg1mJ0o4Gm1iMnW2oZRKnXB5VajZZEX%2BRTqRuo9ACVO2mkUih%2F4l9C8s0MNcFkjLaHW9KSUHlwR506bAnrPMam4RCBOlsYkS1%2BD3MvLcDJxAx9KN4jCkXszrG5cP%2BCVH4y8IM8PYFx2dsQOfuiILWQKLVc2JkPPH7te6HrRxh%2BzUdidwSSIXoiz%2FBZyK1Qp1Nv1yPIjCNn9ZrN0V1AKA4UlzjMY7N13IDKbHjyxXoA5291%2FtzH7I%2FApPet%2FHNawx65hli61FMXeSaTUH%2FMubtvlYU0LfcA1t5cl%2BAO%2FfxGlW%2FVQ1ipsoBCVgJLQ2XHo7385%2BwI%3D");
+            UriBuilder builder = UriBuilder.fromUri("http://localhost:8180/auth/realms/demo/protocol/saml?SAMLRequest=jZJdS8MwFIbvBf9DyX2XNG62hnUwHeLAj7JNL7yRmJ65QJrUnNSPf29WHQp%2BIOQiJM%2FJed%2F3ZIyyMa2YdmFjF%2FDYAYbkpTEWRX9Rks5b4SRqFFY2gCIosZxenAs%2BYKL1LjjlDHkv%2BRuWiOCDdpYk0932xFnsGvBL8E9awfXivCSbEFpBqXFKmo3DIApeMApNa9wrACXJLGrUVm7rf6KzSMtoh3qQpkFaQ%2BPoTinduiLJqfMKes8lWUuDQJL5rCTz2d2wLmCkgKc5Z4fpMOf3qSyO8pTXxUHOjphibBRhrKId%2FQSf5YgdzC0GaUNJOMtGKTtI2eGKcxFXlg%2BK0fCWJNWHkGNta20f%2Fo7s%2Fh1CcbZaVWl1tVyR5AY89s4jQCb7e%2BOtI9G3918m999ZTL4HyIrsM%2B4x%2FfL%2Brl0rLuOT81nljFavydQY93wS4w4xj%2BA76ANuZPhdRDbI%2BhNdp%2BseFZ3FFpRea6gJ3Tai33%2Fm5A0%3D");
+            builder.queryParam("RelayState", RELAY_STATE);
+            resp.setHeader("Location", builder.build().toString());
+            return;
+        }
+
+        System.out.println("Response was received");
+        samlResponse = req.getParameter("SAMLResponse");
+        sentRelayState = req.getParameter("RelayState");
+
+        PrintWriter pw = resp.getWriter();
+        pw.println("Relay state: " + sentRelayState);
+        pw.println("SAML response: " + samlResponse);
+        pw.flush();
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java
index 58feae3..6e70f15 100755
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/servlet/SendUsernameServlet.java
@@ -19,6 +19,10 @@ package org.keycloak.testsuite.adapter.servlet;
 
 
 import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.adapters.saml.SamlAuthenticationError;
+import org.keycloak.adapters.saml.SamlPrincipal;
+import org.keycloak.adapters.spi.AuthenticationError;
+import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
@@ -28,6 +32,9 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.io.IOException;
 import java.security.Principal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -38,6 +45,9 @@ import java.security.Principal;
 public class SendUsernameServlet {
 
     private static boolean checkRoles = false;
+    private static SamlAuthenticationError authError;
+    private static Principal sentPrincipal;
+    private static List<String> checkRolesList = Collections.singletonList("manager");
 
     @Context
     private HttpServletRequest httpServletRequest;
@@ -62,7 +72,15 @@ public class SendUsernameServlet {
             throw new RuntimeException("User: " + httpServletRequest.getUserPrincipal() + " do not have required role");
         }
 
-        return Response.ok(getOutput(), MediaType.TEXT_PLAIN).build();
+        return Response.ok(getOutput(), MediaType.TEXT_HTML_TYPE).build();
+    }
+
+    @GET
+    @Path("getAttributes")
+    public Response getSentPrincipal() throws IOException {
+        System.out.println("In SendUsername Servlet getSentPrincipal()");
+
+        return Response.ok(getAttributes(), MediaType.TEXT_HTML_TYPE).build();
     }
 
     @GET
@@ -79,6 +97,23 @@ public class SendUsernameServlet {
         return doPost(checkRolesFlag);
     }
 
+    @POST
+    @Path("error.html")
+    public Response errorPagePost() {
+        authError = (SamlAuthenticationError) httpServletRequest.getAttribute(AuthenticationError.class.getName());
+        Integer statusCode = (Integer) httpServletRequest.getAttribute("javax.servlet.error.status_code");
+        System.out.println("In SendUsername Servlet errorPage() status code: " + statusCode);
+
+        return Response.ok(getErrorOutput(statusCode), MediaType.TEXT_HTML_TYPE).build();
+    }
+
+    @GET
+    @Path("error.html")
+    public Response errorPageGet() {
+        return errorPagePost();
+    }
+
+
     @GET
     @Path("checkRoles")
     public String checkRolesEndPoint() {
@@ -87,8 +122,35 @@ public class SendUsernameServlet {
         return "Roles will be checked";
     }
 
+    @GET
+    @Path("uncheckRoles")
+    public String uncheckRolesEndPoint() {
+        checkRoles = false;
+        System.out.println("Setting checkRoles to false");
+        checkRolesList = Collections.singletonList("manager");
+        return "Roles will not be checked";
+    }
+
+    @GET
+    @Path("setCheckRoles")
+    public String setCheckRoles(@QueryParam("roles") String roles) {
+        checkRolesList = Arrays.asList(roles.split(","));
+        checkRoles = true;
+        System.out.println("Setting checkRolesList to " + checkRolesList.toString());
+        return "These roles will be checked: " + checkRolesList.toString();
+    }
+
+
     private boolean checkRoles() {
-        return httpServletRequest.isUserInRole("manager");
+        for (String role : checkRolesList) {
+            System.out.println("In checkRoles() checking role " + role + " for user " + httpServletRequest.getUserPrincipal().getName());
+            if (!httpServletRequest.isUserInRole(role)) {
+                System.out.println("User is not in role " + role);
+                return false;
+            }
+        }
+
+        return true;
     }
 
     private String getOutput() {
@@ -102,6 +164,31 @@ public class SendUsernameServlet {
             return output + "null";
         }
 
+        sentPrincipal = principal;
+
         return output + principal.getName();
     }
+
+    private String getErrorOutput(Integer statusCode) {
+        String output = "<html><head><title>Error Page</title></head><body><h1>There was an error</h1>";
+        if (statusCode != null)
+            output += "<br/>HTTP status code: " + statusCode;
+        if (authError != null)
+            output += "<br/>Error info: " + authError.toString();
+        return output + "</body></html>";
+    }
+
+    private String getAttributes() {
+        SamlPrincipal principal = (SamlPrincipal) sentPrincipal;
+        String output = "attribute email: " + principal.getAttribute(X500SAMLProfileConstants.EMAIL.get());
+        output += "<br /> topAttribute: " + principal.getAttribute("topAttribute");
+        output += "<br /> level2Attribute: " + principal.getAttribute("level2Attribute");
+        output += "<br /> group: " + principal.getAttributes("group").toString();
+        output += "<br /> friendlyAttribute email: " + principal.getFriendlyAttribute("email");
+        output += "<br /> phone: " + principal.getAttribute("phone");
+        output += "<br /> friendlyAttribute phone: " + principal.getFriendlyAttribute("phone");
+        output += "<br /> hardcoded-attribute: " + principal.getAttribute("hardcoded-attribute");
+
+        return output;
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
index 984ba7d..d958e6e 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/AuthServerTestEnricher.java
@@ -26,7 +26,7 @@ import org.jboss.arquillian.container.spi.Container;
 import org.jboss.arquillian.container.spi.ContainerRegistry;
 import org.jboss.arquillian.container.spi.event.StartContainer;
 import org.jboss.arquillian.container.spi.event.StartSuiteContainers;
-import org.jboss.arquillian.container.test.api.ContainerController;
+import org.jboss.arquillian.container.spi.event.StopContainer;
 import org.jboss.arquillian.core.api.Event;
 import org.jboss.arquillian.core.api.Instance;
 import org.jboss.arquillian.core.api.InstanceProducer;
@@ -53,10 +53,9 @@ public class AuthServerTestEnricher {
     private Instance<ContainerRegistry> containerRegistry;
 
     @Inject
-    private Instance<ContainerController> containerController;
-
-    @Inject
     private Event<StartContainer> startContainerEvent;
+    @Inject
+    private Event<StopContainer> stopContainerEvent;
 
     private static final String AUTH_SERVER_CONTAINER_DEFAULT = "auth-server-undertow";
     private static final String AUTH_SERVER_CONTAINER_PROPERTY = "auth.server.container";
@@ -65,8 +64,8 @@ public class AuthServerTestEnricher {
     private static final String AUTH_SERVER_CLUSTER_PROPERTY = "auth.server.cluster";
     public static final boolean AUTH_SERVER_CLUSTER = Boolean.parseBoolean(System.getProperty(AUTH_SERVER_CLUSTER_PROPERTY, "false"));
 
-    private static final String MIGRATED_AUTH_SERVER_CONTAINER_PROPERTY = "migrated.auth.server.container";
-    public static final String MIGRATED_AUTH_SERVER_CONTAINER = System.getProperty(MIGRATED_AUTH_SERVER_CONTAINER_PROPERTY); // == null if migration not enabled
+    private static final String MIGRATION_PROPERTY = "auth.server.jboss.migration";
+    private static final Boolean MIGRATION_ENABLED = Boolean.parseBoolean(System.getProperty(MIGRATION_PROPERTY));
 
     @Inject
     @SuiteScoped
@@ -132,23 +131,19 @@ public class AuthServerTestEnricher {
             throw new RuntimeException(String.format("No auth server container matching '%sN' found in arquillian.xml.", authServerBackend));
         }
 
-        if (MIGRATED_AUTH_SERVER_CONTAINER != null) {
+        if (MIGRATION_ENABLED) {
             // init migratedAuthServerInfo
-            if (MIGRATED_AUTH_SERVER_CONTAINER.startsWith("migrated-auth-server-")) {
-                for (ContainerInfo container : suiteContext.getContainers()) {
-                    // migrated auth server
-                    if (container.getQualifier().equals(MIGRATED_AUTH_SERVER_CONTAINER)) {
-                        updateWithAuthServerInfo(container);
-                        suiteContext.setMigratedAuthServerInfo(container);
-                    }
+            for (ContainerInfo container : suiteContext.getContainers()) {
+                // migrated auth server
+                if (container.getQualifier().equals("auth-server-jboss-migration")) {
+                    updateWithAuthServerInfo(container);
+                    suiteContext.setMigratedAuthServerInfo(container);
                 }
-            } else {
-                throw new IllegalArgumentException(String.format("Value of %s should start with 'migrated-auth-server-' prefix.", MIGRATED_AUTH_SERVER_CONTAINER_PROPERTY));
             }
             // validate setup
             if (suiteContext.getMigratedAuthServerInfo() == null) {
                 throw new RuntimeException(String.format("Migration test was enabled but no auth server from which to migrate was activated. "
-                        + "A container matching '%s' needs to be enabled in arquillian.xml.", MIGRATED_AUTH_SERVER_CONTAINER));
+                        + "A container matching auth-server-jboss-migration needs to be enabled in arquillian.xml."));
             }
         }
 
@@ -178,7 +173,8 @@ public class AuthServerTestEnricher {
 
     public void stopMigratedContainer(@Observes(precedence = 1) StartSuiteContainers event) {
         if (suiteContext.isAuthServerMigrationEnabled()) {
-            containerController.get().stop(suiteContext.getAuthServerInfo().getQualifier());
+            log.info("## STOP old container: " + suiteContext.getMigratedAuthServerInfo().getQualifier());
+            stopContainerEvent.fire(new StopContainer(suiteContext.getMigratedAuthServerInfo().getArquillianContainer()));
         }
     }
 
@@ -189,14 +185,6 @@ public class AuthServerTestEnricher {
             LogChecker.checkJBossServerLog(jbossHomePath);
         }
     }
-//
-//    public void startAuthServerContainer(@Observes BeforeSuite event) {
-//        startContainerEvent.fire(new StartContainer(suiteContext.getAuthServerInfo().getArquillianContainer()));
-//    }
-//
-//    public void stopAuthServerContainer(@Observes AfterSuite event) {
-//        containerController.get().stop(suiteContext.getAuthServerInfo().getQualifier());
-//    }
 
     public void initializeTestContext(@Observes(precedence = 2) BeforeClass event) {
         TestContext testContext = new TestContext(suiteContext, event.getTestClass().getJavaClass());
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
index 68d7183..9cd7625 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/DeploymentArchiveProcessor.java
@@ -17,7 +17,6 @@
 
 package org.keycloak.testsuite.arquillian;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.tools.ant.DirectoryScanner;
 import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
 import org.jboss.arquillian.test.spi.TestClass;
@@ -31,6 +30,7 @@ import org.keycloak.testsuite.arquillian.annotation.UseServletFilter;
 import org.keycloak.testsuite.util.IOUtil;
 import org.keycloak.util.JsonSerialization;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 import javax.xml.transform.TransformerException;
 import java.io.File;
@@ -112,6 +112,12 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
                     log.error("Can't transform document to String");
                     throw new RuntimeException(e);
                 }
+
+                // For running SAML tests it is necessary to have few dependencies on app-server side.
+                // Few of them are not in adapter zip so we need to add them manually here
+                log.info("Adding SAMLFilter dependencies to " + archive.getName());
+                ((WebArchive) archive).addAsLibraries(KeycloakDependenciesResolver.resolveDependencies("org.keycloak:keycloak-saml-servlet-filter-adapter:" + System.getProperty("project.version")));
+
             } else { // OIDC adapter config
                 try {
                     AdapterConfig adapterConfig = loadJson(archive.get(adapterConfigPath)
@@ -156,45 +162,58 @@ public class DeploymentArchiveProcessor implements ApplicationArchiveProcessor {
 
     protected void modifyWebXml(Archive<?> archive, TestClass testClass) {
         try {
-            String webXmlContent = IOUtils.toString(
+            Document webXmlDoc = loadXML(
                     archive.get(WEBXML_PATH).getAsset().openStream());
             if (isTomcatAppServer(testClass.getJavaClass())) {
-                webXmlContent = webXmlContent.replace("<auth-method>KEYCLOAK</auth-method>", "<auth-method>BASIC</auth-method>");
+                modifyDocElementValue(webXmlDoc, "auth-method", "KEYCLOAK", "BASIC");
             }
 
             if (testClass.getJavaClass().isAnnotationPresent(UseServletFilter.class)) {
                 //We need to add filter declaration to web.xml
                 log.info("Adding filter to " + testClass.getAnnotation(UseServletFilter.class).filterClass() + " with mapping " + testClass.getAnnotation(UseServletFilter.class).filterPattern() + " for " + archive.getName());
-                String filter = "\n<filter>\n" +
-                        "<filter-name>" + testClass.getAnnotation(UseServletFilter.class).filterName() + "</filter-name>\n" +
-                        "<filter-class>" + testClass.getAnnotation(UseServletFilter.class).filterClass() + "</filter-class>\n" +
-                        "</filter>\n" +
-                        "\n<filter-mapping>\n" +
-                        "<filter-name>" + testClass.getAnnotation(UseServletFilter.class).filterName() + "</filter-name>\n" +
-                        "<url-pattern>" + testClass.getAnnotation(UseServletFilter.class).filterPattern() + "</url-pattern>\n";
-                if (!testClass.getAnnotation(UseServletFilter.class).dispatcherType().isEmpty()) {
-                    filter += "<dispatcher>" + testClass.getAnnotation(UseServletFilter.class).dispatcherType() + "</dispatcher>\n";
-                }
-                filter += "</filter-mapping>\n";
 
-                webXmlContent = webXmlContent.replace("</module-name>", "</module-name> " + filter);
+                Element filter = webXmlDoc.createElement("filter");
+                Element filterName = webXmlDoc.createElement("filter-name");
+                Element filterClass = webXmlDoc.createElement("filter-class");
 
-                //Also we need to add all dependencies within war lib directory, because filter needs to work without installed adapter
-                log.info("Adding SAMLFilter dependencies to " + archive.getName());
-                ((WebArchive) archive).addAsLibraries(new SAMLFilterDependency().getDependencies());
+                filterName.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterName());
+                filterClass.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterClass());
 
+                filter.appendChild(filterName);
+                filter.appendChild(filterClass);
+                appendChildInDocument(webXmlDoc, "web-app", filter);
+
+                Element filterMapping = webXmlDoc.createElement("filter-mapping");
 
-                //finally we need to remove all keycloak related configuration from web.xml
-                int start = webXmlContent.indexOf("<security-constraint>");
-                int end = webXmlContent.indexOf("</security-role>") + "</security-role>".length();
 
+                Element urlPattern = webXmlDoc.createElement("url-pattern");
 
-                webXmlContent = webXmlContent.substring(0, start) + webXmlContent.substring(end);
+                filterName = webXmlDoc.createElement("filter-name");
+
+                filterName.setTextContent(testClass.getAnnotation(UseServletFilter.class).filterName());
+                urlPattern.setTextContent(getElementTextContent(webXmlDoc, "web-app/security-constraint/web-resource-collection/url-pattern"));
+
+                filterMapping.appendChild(filterName);
+                filterMapping.appendChild(urlPattern);
+
+                if (!testClass.getAnnotation(UseServletFilter.class).dispatcherType().isEmpty()) {
+                    Element dispatcher = webXmlDoc.createElement("dispatcher");
+                    dispatcher.setTextContent(testClass.getAnnotation(UseServletFilter.class).dispatcherType());
+                    filterMapping.appendChild(dispatcher);
+                }
+                appendChildInDocument(webXmlDoc, "web-app", filterMapping);
+
+                //finally we need to remove all keycloak related configuration from web.xml
+                removeElementFromDoc(webXmlDoc, "web-app", "security-constraint");
+                removeElementFromDoc(webXmlDoc, "web-app", "login-config");
+                removeElementFromDoc(webXmlDoc, "web-app", "security-role");
             }
 
-            archive.add(new StringAsset((webXmlContent)), WEBXML_PATH);
-        } catch (IOException ex) {
-            throw new RuntimeException("Cannot load web.xml from archive.");
+
+            archive.add(new StringAsset((documentToString(webXmlDoc))), WEBXML_PATH);
+        } catch (TransformerException e) {
+            log.error("Can't transform document to String");
+            throw new RuntimeException(e);
         }
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakDependenciesResolver.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakDependenciesResolver.java
new file mode 100644
index 0000000..2f62c2b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakDependenciesResolver.java
@@ -0,0 +1,39 @@
+package org.keycloak.testsuite.arquillian;
+
+import org.jboss.logging.Logger;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
+import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencies;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author mhajas
+ */
+public class KeycloakDependenciesResolver {
+
+    private static Map<String, File[]> dependencies = new HashMap<>();
+
+    protected static final Logger log = org.jboss.logging.Logger.getLogger(KeycloakDependenciesResolver.class);
+
+    public static File[] resolveDependencies(String canonicalForm) {
+        if (dependencies.containsKey(canonicalForm)) {
+            return dependencies.get(canonicalForm);
+        }
+
+        log.info("Resolving " + canonicalForm + "'s dependencies");
+        PomEquippedResolveStage resolver = Maven.configureResolverViaPlugin();
+
+        File[] files = resolver.addDependency(MavenDependencies.createDependency(canonicalForm, ScopeType.COMPILE, false))
+                .resolve().withTransitivity().asFile();
+
+        dependencies.put(canonicalForm, files);
+
+        log.info("Resolving dependencies is finished with " + files.length + " files");
+
+        return dependencies.get(canonicalForm);
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/migration/MigrationTestExecutionDecider.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/migration/MigrationTestExecutionDecider.java
index 333c5dd..78d26d5 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/migration/MigrationTestExecutionDecider.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/migration/MigrationTestExecutionDecider.java
@@ -38,7 +38,7 @@ public class MigrationTestExecutionDecider implements TestExecutionDecider {
         if (migrationTest && migrationAnnotation != null) {
             String versionFrom = migrationAnnotation.versionFrom();
 
-            if (migratedAuthServerVersion.equals(versionFrom)) {
+            if (versionFrom.equals(migratedAuthServerVersion)) {
                 return ExecutionDecision.execute();
             } else {
                 return ExecutionDecision.dontExecute(method.getName() + "doesn't fit with migration version.");
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java
index 929c23d..d576b49 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/SuiteContext.java
@@ -98,6 +98,9 @@ public final class SuiteContext {
         for (ContainerInfo bInfo : getAuthServerBackendsInfo()) {
             containers += "Backend: " + bInfo + "\n";
         }
+        if (isAuthServerMigrationEnabled()) {
+            containers += "Migrated from: " + System.getProperty("migrated.auth.server.version") + "\n";
+        }
         return "SUITE CONTEXT:\n"
                 + containers;
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java
index 2efc26b..2d277fd 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResource.java
@@ -20,7 +20,9 @@ package org.keycloak.testsuite.client.resources;
 import org.keycloak.representations.adapters.action.LogoutAction;
 import org.keycloak.representations.adapters.action.PushNotBeforeAction;
 import org.keycloak.representations.adapters.action.TestAvailabilityAction;
+import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
 
+import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -53,4 +55,6 @@ public interface TestApplicationResource {
     @Path("/clear-admin-actions")
     Response clearAdminActions();
 
+    @Path("/oidc-client-endpoints")
+    TestOIDCEndpointsApplicationResource oidcClientEndpoints();
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java
new file mode 100644
index 0000000..8c5f98b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestApplicationResourceUrls.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.client.resources;
+
+import javax.ws.rs.core.UriBuilder;
+
+import org.keycloak.testsuite.util.OAuthClient;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class TestApplicationResourceUrls {
+
+    private static UriBuilder oidcClientEndpoints() {
+        return UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)
+                .path(TestApplicationResource.class)
+                .path(TestApplicationResource.class, "oidcClientEndpoints");
+    }
+
+    public static String clientRequestUri() {
+        UriBuilder builder = oidcClientEndpoints()
+                .path(TestOIDCEndpointsApplicationResource.class, "getOIDCRequest");
+
+        return builder.build().toString();
+    }
+
+    public static String clientJwksUri() {
+        UriBuilder builder = oidcClientEndpoints()
+                .path(TestOIDCEndpointsApplicationResource.class, "getJwks");
+
+        return builder.build().toString();
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingExportImportResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingExportImportResource.java
new file mode 100644
index 0000000..27fa360
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingExportImportResource.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.client.resources;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface TestingExportImportResource {
+
+    @GET
+    @Path("/run-import")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response runImport();
+
+    @GET
+    @Path("/run-export")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response runExport();
+
+    @GET
+    @Path("/get-users-per-file")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Integer getUsersPerFile();
+
+    @PUT
+    @Path("/set-users-per-file")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setUsersPerFile(@QueryParam("usersPerFile") Integer usersPerFile);
+
+    @GET
+    @Path("/get-dir")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getDir();
+
+    @PUT
+    @Path("/set-dir")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String setDir(@QueryParam("dir") String dir);
+
+    @PUT
+    @Path("/export-import-provider")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setProvider(@QueryParam("exportImportProvider") String exportImportProvider);
+
+    @PUT
+    @Path("/export-import-file")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setFile(@QueryParam("file") String file);
+
+    @PUT
+    @Path("/export-import-action")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setAction(@QueryParam("exportImportAction") String exportImportAction);
+
+    @PUT
+    @Path("/set-realm-name")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public void setRealmName(@QueryParam("realmName") String realmName);
+
+    @GET
+    @Path("/get-test-dir")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getExportImportTestDirectory();
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
index fcf5d83..0dbcd58 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
@@ -17,8 +17,8 @@
 
 package org.keycloak.testsuite.client.resources;
 
-import java.util.Date;
 import java.util.List;
+
 import org.keycloak.representations.idm.AdminEventRepresentation;
 import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
@@ -37,7 +37,6 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.Map;
 import org.jboss.resteasy.annotations.cache.NoCache;
-import org.keycloak.exportimport.ExportImportManager;
 
 /**
  * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
@@ -205,16 +204,6 @@ public interface TestingResource {
     @Path("/update-pass-through-auth-state")
     @Produces(MediaType.APPLICATION_JSON)
     AuthenticatorState updateAuthenticator(AuthenticatorState state);
-
-    @GET
-    @Path("/run-import")
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response runImport();
-
-    @GET
-    @Path("/run-export")
-    @Produces(MediaType.APPLICATION_JSON)
-    public Response runExport();
     
     @GET
     @Path("/valid-credentials")
@@ -250,53 +239,7 @@ public interface TestingResource {
     @Produces(MediaType.APPLICATION_JSON)
     public UserRepresentation getUserByServiceAccountClient(@QueryParam("realmName") String realmName, @QueryParam("clientId") String clientId);
 
+    @Path("export-import")
+    TestingExportImportResource exportImport();
 
-    @GET
-    @Path("/get-users-per-file")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public Integer getUsersPerFile();
-
-    @PUT
-    @Path("/set-users-per-file")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setUsersPerFile(@QueryParam("usersPerFile") Integer usersPerFile);
-
-    @GET
-    @Path("/get-dir")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public String getDir();
-
-    @PUT
-    @Path("/set-dir")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public String setDir(@QueryParam("dir") String dir);
-
-    @PUT
-    @Path("/export-import-provider")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setProvider(@QueryParam("exportImportProvider") String exportImportProvider);
-
-    @PUT
-    @Path("/export-import-file")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setFile(@QueryParam("file") String file);
-
-    @PUT
-    @Path("/export-import-action")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setAction(@QueryParam("exportImportAction") String exportImportAction);
-
-    @PUT
-    @Path("/set-realm-name")
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void setRealmName(@QueryParam("realmName") String realmName);
-
-    @GET
-    @Path("/get-test-dir")
-    @Consumes(MediaType.APPLICATION_JSON)
-    @Produces(MediaType.APPLICATION_JSON)
-    public String getExportImportTestDirectory();
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java
new file mode 100644
index 0000000..54d6c35
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestOIDCEndpointsApplicationResource.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.client.resources;
+
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.keycloak.jose.jwk.JSONWebKeySet;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface TestOIDCEndpointsApplicationResource {
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/generate-keys")
+    Map<String, String> generateKeys();
+
+
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("/get-jwks")
+    JSONWebKeySet getJwks();
+
+
+    @GET
+    @Path("/set-oidc-request")
+    @Produces(org.keycloak.utils.MediaType.APPLICATION_JWT)
+    void setOIDCRequest(@QueryParam("realmName") String realmName, @QueryParam("clientId") String clientId,
+                        @QueryParam("redirectUri") String redirectUri, @QueryParam("maxAge") String maxAge,
+                        @QueryParam("jwaAlgorithm") String jwaAlgorithm);
+
+    @GET
+    @Path("/get-oidc-request")
+    @Produces(org.keycloak.utils.MediaType.APPLICATION_JWT)
+    String getOIDCRequest();
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
index d872914..89084d4 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/IOUtil.java
@@ -16,9 +16,11 @@
  */
 package org.keycloak.testsuite.util;
 
+import org.jboss.logging.Logger;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.util.JsonSerialization;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
@@ -33,7 +35,6 @@ import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 import java.io.*;
 import java.util.concurrent.TimeUnit;
-import org.jboss.logging.Logger;
 
 /**
  *
@@ -93,18 +94,99 @@ public class IOUtil {
     public static void modifyDocElementAttribute(Document doc, String tagName, String attributeName, String regex, String replacement) {
         NodeList nodes = doc.getElementsByTagName(tagName);
         if (nodes.getLength() != 1) {
-            System.out.println("Not able to find element: " + tagName);
+            log.warn("Not able or ambiguous to find element: " + tagName);
             return;
         }
 
         Node node = nodes.item(0).getAttributes().getNamedItem(attributeName);
         if (node == null) {
-            System.out.println("Not able to find attribute " + attributeName + " within element: " + tagName);
+            log.warn("Not able to find attribute " + attributeName + " within element: " + tagName);
+            return;
+        }
+        node.setTextContent(node.getTextContent().replace(regex, replacement));
+    }
+
+    public static void modifyDocElementValue(Document doc, String tagName, String regex, String replacement) {
+        NodeList nodes = doc.getElementsByTagName(tagName);
+        if (nodes.getLength() != 1) {
+            log.warn("Not able or ambiguous to find element: " + tagName);
+            return;
+        }
+
+        Node node = nodes.item(0);
+        if (node == null) {
+            log.warn("Not able to find element: " + tagName);
             return;
         }
+
         node.setTextContent(node.getTextContent().replace(regex, replacement));
     }
 
+    public static void removeElementFromDoc(Document doc, String parentTag, String removeNode) {
+        NodeList nodes = doc.getElementsByTagName(parentTag);
+        if (nodes.getLength() != 1) {
+            log.warn("Not able or ambiguous to find element: " + parentTag);
+            return;
+        }
+
+        Element parentElement = (Element) nodes.item(0);
+        if (parentElement == null) {
+            log.warn("Not able to find element: " + parentTag);
+            return;
+        }
+
+        NodeList removeNodes = parentElement.getElementsByTagName(removeNode);
+        if (removeNodes.getLength() != 1) {
+            log.warn("Not able or ambiguous to find element: " + removeNode + " within node " + parentTag);
+            return;
+        }
+
+        Element removeElement = (Element) removeNodes.item(0);
+        if (removeElement == null) {
+            log.warn("Not able to find element: " + removeNode + " within node " + parentTag);
+            return;
+        }
+
+        parentElement.removeChild(removeElement);
+    }
+
+    public static String getElementTextContent(Document doc, String path) {
+        String[] pathSegments = path.split("/");
+
+        Element currentElement = (Element) doc.getElementsByTagName(pathSegments[0]).item(0);
+        if (currentElement == null) {
+            log.warn("Not able to find element: " + pathSegments[0] + " in document");
+            return null;
+        }
+
+        for (int i = 1; i < pathSegments.length; i++) {
+            currentElement = (Element) currentElement.getElementsByTagName(pathSegments[i]).item(0);
+
+            if (currentElement == null) {
+                log.warn("Not able to find element: " + pathSegments[i] + " in " + pathSegments[i - 1]);
+                return null;
+            }
+        }
+
+        return currentElement.getTextContent();
+    }
+
+    public static void appendChildInDocument(Document doc, String parentTag, Element node) {
+        NodeList nodes = doc.getElementsByTagName(parentTag);
+        if (nodes.getLength() != 1) {
+            log.warn("Not able or ambiguous to find element: " + parentTag);
+            return;
+        }
+
+        Element parentElement = (Element) nodes.item(0);
+        if (parentElement == null) {
+            log.warn("Not able to find element: " + parentTag);
+            return;
+        }
+
+        parentElement.appendChild(node);
+    }
+
     public static void execCommand(String command, File dir) throws IOException, InterruptedException {
         Process process = Runtime.getRuntime().exec(command, null, dir);
         if (process.waitFor(10, TimeUnit.SECONDS)) {
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
index 586351d..2253828 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
@@ -105,6 +105,10 @@ public class OAuthClient {
 
     private String nonce;
 
+    private String request;
+
+    private String requestUri;
+
     private Map<String, PublicKey> publicKeys = new HashMap<>();
 
     public void init(Keycloak adminClient, WebDriver driver) {
@@ -121,6 +125,9 @@ public class OAuthClient {
         clientSessionState = null;
         clientSessionHost = null;
         maxAge = null;
+        nonce = null;
+        request = null;
+        requestUri = null;
     }
 
     public AuthorizationEndpointResponse doLogin(String username, String password) {
@@ -536,6 +543,12 @@ public class OAuthClient {
         if (maxAge != null) {
             b.queryParam(OIDCLoginProtocol.MAX_AGE_PARAM, maxAge);
         }
+        if (request != null) {
+            b.queryParam(OIDCLoginProtocol.REQUEST_PARAM, request);
+        }
+        if (requestUri != null) {
+            b.queryParam(OIDCLoginProtocol.REQUEST_URI_PARAM, requestUri);
+        }
         return b.build(realm).toString();
     }
 
@@ -644,6 +657,16 @@ public class OAuthClient {
         return this;
     }
 
+    public OAuthClient request(String request) {
+        this.request = request;
+        return this;
+    }
+
+    public OAuthClient requestUri(String requestUri) {
+        this.requestUri = requestUri;
+        return this;
+    }
+
     public String getRealm() {
         return realm;
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java
index dd6a3db..b5af7c9 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/UserInfoClientUtil.java
@@ -28,6 +28,7 @@ import javax.ws.rs.core.UriBuilder;
 import org.junit.Assert;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.UserInfo;
+import org.keycloak.utils.MediaType;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -51,6 +52,7 @@ public class UserInfoClientUtil {
 
     public static void testSuccessfulUserInfoResponse(Response response, String expectedUsername, String expectedEmail) {
         Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+        Assert.assertEquals(response.getHeaderString(HttpHeaders.CONTENT_TYPE), MediaType.APPLICATION_JSON);
 
         UserInfo userInfo = response.readEntity(UserInfo.class);
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
index 0ef7215..63821b3 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractAdapterTest.java
@@ -31,6 +31,7 @@ import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  *
@@ -63,10 +64,12 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
                 modifyClientUrls(tr, appServerContextRootPage.toString(), "");
                 modifyClientWebOrigins(tr, "8080", System.getProperty("auth.server.http.port", null));
                 modifySamlMasterURLs(tr, "/", "http://localhost:" + System.getProperty("auth.server.http.port", null) + "/");
+                modifySAMLClientsAttributes(tr, "8080", System.getProperty("auth.server.http.port", "8180"));
             } else {
                 modifyClientRedirectUris(tr, "^(/.*/\\*)", appServerContextRootPage.toString() + "$1");
                 modifyClientUrls(tr, "^(/.*)", appServerContextRootPage.toString() + "$1");
                 modifySamlMasterURLs(tr, "8080", System.getProperty("auth.server.http.port", null));
+                modifySAMLClientsAttributes(tr, "8080", System.getProperty("app.server.http.port", "8280"));
             }
             if ("true".equals(System.getProperty("auth.server.ssl.required"))) {
                 tr.setSslRequired("all");
@@ -125,6 +128,19 @@ public abstract class AbstractAdapterTest extends AbstractAuthTest {
         }
     }
 
+    protected void modifySAMLClientsAttributes(RealmRepresentation realm, String regex, String replacement) {
+        if (realm.getClients() != null) {
+            for (ClientRepresentation client : realm.getClients()) {
+                if (client.getProtocol() != null && client.getProtocol().equals("saml")) {
+                    log.info("Modifying attributes of SAML client: " + client.getClientId());
+                    for (Map.Entry<String, String> entry : client.getAttributes().entrySet()) {
+                        client.getAttributes().put(entry.getKey(), entry.getValue().replaceAll(regex, replacement));
+                    }
+                }
+            }
+        }
+    }
+
     protected void modifySamlMasterURLs(RealmRepresentation realm, String regex, String replacement) {
         if (realm.getClients() != null) {
             for (ClientRepresentation client : realm.getClients()) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
index badf51c..127c863 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java
@@ -25,12 +25,11 @@ import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.util.WaitUtils;
 import org.openqa.selenium.By;
 
+import javax.ws.rs.core.UriBuilder;
 import java.io.IOException;
 import java.net.URL;
 import java.util.List;
 
-import javax.ws.rs.core.UriBuilder;
-
 import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
 import static org.keycloak.testsuite.util.IOUtil.loadRealm;
 
@@ -66,15 +65,15 @@ public abstract class AbstractServletsAdapterTest extends AbstractAdapterTest {
     }
 
     protected static WebArchive samlServletDeployment(String name, Class... servletClasses) {
-        return samlServletDeployment(name, "keycloak-saml.xml", servletClasses);
+        return samlServletDeployment(name, "web.xml", servletClasses);
     }
 
-    protected static WebArchive samlServletDeployment(String name, String adapterConfig ,Class... servletClasses) {
+    protected static WebArchive samlServletDeployment(String name, String webXMLPath, Class... servletClasses) {
         String baseSAMLPath = "/adapter-test/keycloak-saml/";
         String webInfPath = baseSAMLPath + name + "/WEB-INF/";
 
-        URL keycloakSAMLConfig = AbstractServletsAdapterTest.class.getResource(webInfPath + adapterConfig);
-        URL webXML = AbstractServletsAdapterTest.class.getResource(baseSAMLPath + "web.xml");
+        URL keycloakSAMLConfig = AbstractServletsAdapterTest.class.getResource(webInfPath + "keycloak-saml.xml");
+        URL webXML = AbstractServletsAdapterTest.class.getResource(baseSAMLPath + webXMLPath);
 
         WebArchive deployment = ShrinkWrap.create(WebArchive.class, name + ".war")
                 .addClasses(servletClasses)
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java
new file mode 100644
index 0000000..4236b2e
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/EnforcerConfigTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.testsuite.adapter.example.authorization;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.authorization.PolicyEnforcer;
+import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.AbstractKeycloakTest;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.keycloak.testsuite.util.IOUtil.loadRealm;
+
+/**
+ * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
+ */
+public class EnforcerConfigTest extends AbstractKeycloakTest {
+
+    @Override
+    public void addTestRealms(List<RealmRepresentation> testRealms) {
+        RealmRepresentation realm = loadRealm(getClass().getResourceAsStream("/authorization-test/test-authz-realm.json"));
+        testRealms.add(realm);
+    }
+
+    @Test
+    public void testMultiplePathsWithSameName() throws Exception{
+        KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(getClass().getResourceAsStream("/authorization-test/enforcer-config-paths-same-name.json"));
+        PolicyEnforcer policyEnforcer = deployment.getPolicyEnforcer();
+        List<PolicyEnforcerConfig.PathConfig> paths = policyEnforcer.getPaths();
+        assertEquals(1, paths.size());
+        assertEquals(4, paths.get(0).getMethods().size());
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java
index 0df65a4..268285a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLFilterServletAdapterTest.java
@@ -2,6 +2,8 @@ package org.keycloak.testsuite.adapter.servlet;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
 import org.keycloak.testsuite.arquillian.annotation.UseServletFilter;
 
 /**
@@ -25,11 +27,12 @@ public abstract class AbstractSAMLFilterServletAdapterTest extends AbstractSAMLS
         salesPostSigEmailServletPage.checkRoles(true);
         salesPostSigPersistentServletPage.checkRoles(true);
         salesPostSigTransientServletPage.checkRoles(true);
-        employee2ServletPage.navigateTo();
+        salesPostAssertionAndResponseSigPage.checkRoles(true);
 
         //using endpoint instead of query param because we are not able to put query param to IDP initiated login
+        employee2ServletPage.navigateTo();
         testRealmLoginPage.form().login(bburkeUser);
-        employee2ServletPage.checkRolesEndPoint();
+        employee2ServletPage.checkRolesEndPoint(true);
         employee2ServletPage.logout();
 
         forbiddenIfNotAuthenticated = false;
@@ -51,4 +54,18 @@ public abstract class AbstractSAMLFilterServletAdapterTest extends AbstractSAMLS
         salesPostSigPersistentServletPage.checkRoles(false);
         salesPostSigTransientServletPage.checkRoles(false);
     }
+
+    @Test
+    @Override
+    @Ignore
+    public void testSavedPostRequest() {
+
+    }
+
+    @Test
+    @Override
+    @Ignore
+    public void testErrorHandling() {
+
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
index ddc23b7..2973caa 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractSAMLServletsAdapterTest.java
@@ -20,11 +20,19 @@ package org.keycloak.testsuite.adapter.servlet;
 import org.jboss.arquillian.container.test.api.Deployment;
 import org.jboss.arquillian.graphene.page.Page;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assert;
 import org.junit.Test;
 import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.ProtocolMappersResource;
+import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
+import org.keycloak.protocol.saml.mappers.RoleListMapper;
 import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.saml.BaseSAML2BindingBuilder;
+import org.keycloak.saml.SAML2ErrorResponseBuilder;
+import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
 import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
 import org.keycloak.testsuite.adapter.page.*;
 import org.keycloak.testsuite.admin.ApiUtil;
@@ -35,8 +43,15 @@ import org.keycloak.testsuite.util.IOUtil;
 import org.openqa.selenium.By;
 import org.w3c.dom.Document;
 
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Form;
 import javax.ws.rs.core.Response;
+import java.net.URI;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -71,6 +86,9 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
     protected SalesPostServlet salesPostServletPage;
 
     @Page
+    private SalesPost2Servlet salesPost2ServletPage;
+
+    @Page
     protected SalesPostEncServlet salesPostEncServletPage;
 
     @Page
@@ -93,6 +111,26 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
 
     protected boolean forbiddenIfNotAuthenticated = true;
 
+    @Page
+    protected SalesPostAssertionAndResponseSig salesPostAssertionAndResponseSigPage;
+
+    @Page
+    protected BadAssertionSalesPostSig badAssertionSalesPostSigPage;
+
+    @Page
+    protected MissingAssertionSig missingAssertionSigPage;
+
+    @Page
+    protected EmployeeServlet employeeServletPage;
+
+    @Page
+    private InputPortal inputPortalPage;
+
+    @Page
+    private SAMLIDPInitiatedLogin samlidpInitiatedLoginPage;
+
+    public static final String FORBIDDEN_TEXT = "HTTP status code: 403";
+
     @Deployment(name = BadClientSalesPostSigServlet.DEPLOYMENT_NAME)
     protected static WebArchive badClientSalesPostSig() {
         return samlServletDeployment(BadClientSalesPostSigServlet.DEPLOYMENT_NAME, SendUsernameServlet.class);
@@ -158,6 +196,36 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         return samlServletDeployment(SalesPostSigTransientServlet.DEPLOYMENT_NAME, SendUsernameServlet.class);
     }
 
+    @Deployment(name = InputPortal.DEPLOYMENT_NAME)
+    protected static WebArchive inputPortal() {
+        return samlServletDeployment(InputPortal.DEPLOYMENT_NAME, "input-portal/WEB-INF/web.xml" , InputServlet.class);
+    }
+
+    @Deployment(name = SalesPost2Servlet.DEPLOYMENT_NAME)
+    protected static WebArchive salesPost2() {
+        return samlServletDeployment(SalesPost2Servlet.DEPLOYMENT_NAME, SendUsernameServlet.class);
+    }
+
+    @Deployment(name = SalesPostAssertionAndResponseSig.DEPLOYMENT_NAME)
+    protected static WebArchive salesPostAssertionAndResponseSig() {
+        return samlServletDeployment(SalesPostAssertionAndResponseSig.DEPLOYMENT_NAME, SendUsernameServlet.class);
+    }
+
+    @Deployment(name = BadAssertionSalesPostSig.DEPLOYMENT_NAME)
+    protected static WebArchive badAssertionSalesPostSig() {
+        return samlServletDeployment(BadAssertionSalesPostSig.DEPLOYMENT_NAME, SendUsernameServlet.class);
+    }
+
+    @Deployment(name = MissingAssertionSig.DEPLOYMENT_NAME)
+    protected static WebArchive missingAssertionSig() {
+        return samlServletDeployment(MissingAssertionSig.DEPLOYMENT_NAME, SendUsernameServlet.class);
+    }
+
+    @Deployment(name = EmployeeServlet.DEPLOYMENT_NAME)
+    protected static WebArchive employeeServlet() {
+        return samlServletDeployment(EmployeeServlet.DEPLOYMENT_NAME, "employee/WEB-INF/web.xml", SamlSPFacade.class);
+    }
+
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
         testRealms.add(loadRealm("/adapter-test/keycloak-saml/testsaml.json"));
@@ -171,38 +239,54 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         testRealmSAMLPostLoginPage.setAuthRealm(SAMLSERVLETDEMO);
     }
 
-    private void assertForbidden(AbstractPage page) {
+    private void assertForbidden(AbstractPage page, String expectedNotContains) {
         page.navigateTo();
-        waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
-        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("Status 403"));
+        waitUntilElement(By.xpath("//body")).text().not().contains(expectedNotContains);
+        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
     }
 
-    private void assertSuccessfullyLoggedIn(AbstractPage page) {
+    private void assertSuccessfullyLoggedIn(AbstractPage page, String expectedText) {
         page.navigateTo();
-        waitUntilElement(By.xpath("//body")).text().contains("principal=bburke");
+        waitUntilElement(By.xpath("//body")).text().contains(expectedText);
     }
 
-    private void assertForbiddenLogin(AbstractPage page, String username, String password, Login loginPage) {
+    private void assertForbiddenLogin(AbstractPage page, String username, String password, Login loginPage, String expectedNotContains) {
         page.navigateTo();
         assertCurrentUrlStartsWith(loginPage);
         loginPage.form().login(username, password);
-        waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
+        waitUntilElement(By.xpath("//body")).text().not().contains(expectedNotContains);
         //Different 403 status page on EAP and Wildfly
-        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("Status 403"));
+        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
     }
 
-    private void assertSuccessfulLogin(AbstractPage page, UserRepresentation user, Login loginPage) {
+    private void assertSuccessfulLogin(AbstractPage page, UserRepresentation user, Login loginPage, String expectedString) {
         page.navigateTo();
         assertCurrentUrlStartsWith(loginPage);
         loginPage.form().login(user);
-        waitUntilElement(By.xpath("//body")).text().contains("principal=bburke");
+        waitUntilElement(By.xpath("//body")).text().contains(expectedString);
     }
 
     private void testSuccessfulAndUnauthorizedLogin(SAMLServlet page, Login loginPage) {
-        assertSuccessfulLogin(page, bburkeUser, loginPage);
+        testSuccessfulAndUnauthorizedLogin(page, loginPage, "principal=bburke");
+    }
+
+    private void testSuccessfulAndUnauthorizedLogin(SAMLServlet page, Login loginPage, String expectedText) {
+        testSuccessfulAndUnauthorizedLogin(page, loginPage, expectedText, "principal=");
+    }
+
+    private void testSuccessfulAndUnauthorizedLogin(SAMLServlet page, Login loginPage, String expectedText, String expectedNotContains) {
+        assertSuccessfulLogin(page, bburkeUser, loginPage, expectedText);
         page.logout();
-        assertForbiddenLogin(page, "unauthorized", "password", loginPage);
+        checkLoggedOut(page, loginPage);
+        assertForbiddenLogin(page, "unauthorized", "password", loginPage, expectedNotContains);
         page.logout();
+        checkLoggedOut(page, loginPage);
+    }
+
+    private void checkLoggedOut(AbstractPage page, Login loginPage) {
+        page.navigateTo();
+        waitUntilElement(By.xpath("//body")).is().present();
+        assertCurrentUrlStartsWith(loginPage);
     }
 
     @Test
@@ -221,38 +305,35 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
 
     @Test
     public void unauthorizedSSOTest() {
-        assertForbiddenLogin(salesPostServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage);
-        assertForbidden(employee2ServletPage);
-        assertForbidden(employeeSigFrontServletPage);
-        assertForbidden(salesPostSigPersistentServletPage);
+        assertForbiddenLogin(salesPostServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage, "principal=");
+        assertForbidden(employee2ServletPage, "principal=");
+        assertForbidden(employeeSigFrontServletPage, "principal=");
+        assertForbidden(salesPostSigPersistentServletPage, "principal=");
         salesPostServletPage.logout();
+        checkLoggedOut(salesPostServletPage, testRealmSAMLPostLoginPage);
     }
 
     @Test
     public void singleLoginAndLogoutSAMLTest() {
-        assertSuccessfulLogin(salesPostServletPage, bburkeUser, testRealmSAMLPostLoginPage);
-        assertSuccessfullyLoggedIn(salesPostSigServletPage);
-        assertSuccessfullyLoggedIn(employee2ServletPage);
-        assertSuccessfullyLoggedIn(salesPostEncServletPage);
+        assertSuccessfulLogin(salesPostServletPage, bburkeUser, testRealmSAMLPostLoginPage, "principal=bburke");
+        assertSuccessfullyLoggedIn(salesPostSigServletPage, "principal=bburke");
+        assertSuccessfullyLoggedIn(employee2ServletPage, "principal=bburke");
+        assertSuccessfullyLoggedIn(salesPostEncServletPage, "principal=bburke");
 
         employeeSigFrontServletPage.logout();
 
-        employeeSigFrontServletPage.navigateTo();
-        assertCurrentUrlStartsWith(testRealmSAMLRedirectLoginPage);
-
-        employeeSigServletPage.navigateTo();
-        assertCurrentUrlStartsWith(testRealmSAMLRedirectLoginPage);
+        checkLoggedOut(employeeSigFrontServletPage, testRealmSAMLRedirectLoginPage);
+        checkLoggedOut(employeeSigServletPage, testRealmSAMLRedirectLoginPage);
 
         salesPostPassiveServletPage.navigateTo();
         if (forbiddenIfNotAuthenticated) {
             waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
-            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("<body></body>") || driver.getPageSource().equals(""));
+            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
         } else {
             waitUntilElement(By.xpath("//body")).text().contains("principal=null");
         }
 
-        salesPostSigEmailServletPage.navigateTo();
-        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        checkLoggedOut(salesPostSigEmailServletPage, testRealmSAMLPostLoginPage);
     }
 
     @Test
@@ -268,7 +349,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
 
         waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
         //Different 403 status page on EAP and Wildfly
-        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("Status 403"));
+        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
     }
 
     @Test
@@ -328,14 +409,14 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         if (forbiddenIfNotAuthenticated) {
             waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
             //Different 403 status page on EAP and Wildfly
-            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("<body></body>") || driver.getPageSource().equals(""));
+            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
         } else {
             waitUntilElement(By.xpath("//body")).text().contains("principal=null");
         }
 
-        assertSuccessfulLogin(salesPostServletPage, bburkeUser, testRealmSAMLPostLoginPage);
+        assertSuccessfulLogin(salesPostServletPage, bburkeUser, testRealmSAMLPostLoginPage, "principal=bburke");
 
-        assertSuccessfullyLoggedIn(salesPostPassiveServletPage);
+        assertSuccessfullyLoggedIn(salesPostPassiveServletPage, "principal=bburke");
 
         salesPostPassiveServletPage.logout();
         salesPostPassiveServletPage.navigateTo();
@@ -343,12 +424,13 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         if (forbiddenIfNotAuthenticated) {
             waitUntilElement(By.xpath("//body")).text().not().contains("principal=");
             //Different 403 status page on EAP and Wildfly
-            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("<body></body>") || driver.getPageSource().equals(""));
+            assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
         } else {
             waitUntilElement(By.xpath("//body")).text().contains("principal=null");
         }
-        assertForbiddenLogin(salesPostServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage);
-        assertForbidden(salesPostPassiveServletPage);
+
+        assertForbiddenLogin(salesPostServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage, "principal=");
+        assertForbidden(salesPostPassiveServletPage, "principal=");
 
         salesPostPassiveServletPage.logout();
     }
@@ -360,7 +442,7 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
 
     @Test
     public void salesPostSigEmailTest() {
-        testSuccessfulAndUnauthorizedLogin(salesPostSigEmailServletPage, testRealmSAMLPostLoginPage);
+        testSuccessfulAndUnauthorizedLogin(salesPostSigEmailServletPage, testRealmSAMLPostLoginPage, "principal=bburke@redhat.com");
     }
 
     @Test
@@ -371,9 +453,11 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         waitUntilElement(By.xpath("//body")).text().contains("principal=G-");
 
         salesPostSigPersistentServletPage.logout();
+        checkLoggedOut(salesPostSigPersistentServletPage, testRealmSAMLPostLoginPage);
 
-        assertForbiddenLogin(salesPostSigPersistentServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage);
+        assertForbiddenLogin(salesPostSigPersistentServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage, "principal=");
         salesPostSigPersistentServletPage.logout();
+        checkLoggedOut(salesPostSigPersistentServletPage, testRealmSAMLPostLoginPage);
     }
 
     @Test
@@ -384,36 +468,260 @@ public abstract class AbstractSAMLServletsAdapterTest extends AbstractServletsAd
         waitUntilElement(By.xpath("//body")).text().contains("principal=G-");
 
         salesPostSigTransientServletPage.logout();
+        checkLoggedOut(salesPostSigTransientServletPage, testRealmSAMLPostLoginPage);
 
-        assertForbiddenLogin(salesPostSigTransientServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage);
+        assertForbiddenLogin(salesPostSigTransientServletPage, "unauthorized", "password", testRealmSAMLPostLoginPage, "principal=");
         salesPostSigTransientServletPage.logout();
+        checkLoggedOut(salesPostSigTransientServletPage, testRealmSAMLPostLoginPage);
     }
 
     @Test
     public void idpInitiatedLogin() {
-        samlidpInitiatedLogin.setAuthRealm(SAMLSERVLETDEMO);
-        samlidpInitiatedLogin.setUrlName("employee2");
-        samlidpInitiatedLogin.navigateTo();
-        samlidpInitiatedLogin.form().login(bburkeUser);
+        samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO);
+        samlidpInitiatedLoginPage.setUrlName("employee2");
+        samlidpInitiatedLoginPage.navigateTo();
+        samlidpInitiatedLoginPage.form().login(bburkeUser);
 
         waitUntilElement(By.xpath("//body")).text().contains("principal=bburke");
 
-        assertSuccessfullyLoggedIn(salesPostSigServletPage);
+        assertSuccessfullyLoggedIn(salesPostSigServletPage, "principal=bburke");
 
         employee2ServletPage.logout();
+        checkLoggedOut(employee2ServletPage, testRealmSAMLPostLoginPage);
     }
 
     @Test
     public void idpInitiatedUnauthorizedLoginTest() {
-        samlidpInitiatedLogin.setAuthRealm(SAMLSERVLETDEMO);
-        samlidpInitiatedLogin.setUrlName("employee2");
-        samlidpInitiatedLogin.navigateTo();
-        samlidpInitiatedLogin.form().login("unauthorized", "password");
+        samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO);
+        samlidpInitiatedLoginPage.setUrlName("employee2");
+        samlidpInitiatedLoginPage.navigateTo();
+        samlidpInitiatedLoginPage.form().login("unauthorized", "password");
 
         waitUntilElement(By.xpath("//body")).text().not().contains("bburke");
-        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains("Status 403"));
+        assertTrue(driver.getPageSource().contains("Forbidden") || driver.getPageSource().contains(FORBIDDEN_TEXT));
+
+        assertForbidden(employee2ServletPage, "principal=");
+        employee2ServletPage.logout();
+        checkLoggedOut(employee2ServletPage, testRealmSAMLPostLoginPage);
+    }
+
+    @Test
+    public void testSavedPostRequest() {
+        inputPortalPage.navigateTo();
+        assertCurrentUrlStartsWith(inputPortalPage);
+        inputPortalPage.execute("hello");
+
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmLoginPage.form().login("bburke@redhat.com", "password");
+        Assert.assertEquals(driver.getCurrentUrl(), inputPortalPage + "/secured/post");
+        waitUntilElement(By.xpath("//body")).text().contains("parameter=hello");
+
+        // test that user principal and KeycloakSecurityContext available
+        driver.navigate().to(inputPortalPage + "/insecure");
+        waitUntilElement(By.xpath("//body")).text().contains("Insecure Page");
+
+        if (System.getProperty("insecure.user.principal.unsupported") == null) waitUntilElement(By.xpath("//body")).text().contains("UserPrincipal");
+
+        // test logout
+
+        inputPortalPage.logout();
+
+        // test unsecured POST KEYCLOAK-901
 
-        assertForbidden(employee2ServletPage);
+        Client client = ClientBuilder.newClient();
+        Form form = new Form();
+        form.param("parameter", "hello");
+        String text = client.target(inputPortalPage + "/unsecured").request().post(Entity.form(form), String.class);
+        Assert.assertTrue(text.contains("parameter=hello"));
+        client.close();
+    }
+
+    @Test
+    public void testPostSimpleLoginLogoutIdpInitiatedRedirectTo() {
+        samlidpInitiatedLoginPage.setAuthRealm(SAMLSERVLETDEMO);
+        samlidpInitiatedLoginPage.setUrlName("sales-post2");
+        samlidpInitiatedLoginPage.navigateTo();
+
+        samlidpInitiatedLoginPage.form().login(bburkeUser);
+        assertCurrentUrlStartsWith(salesPost2ServletPage);
+        assertTrue(driver.getCurrentUrl().endsWith("/foo"));
+        waitUntilElement(By.xpath("//body")).text().contains("principal=bburke");
+        salesPost2ServletPage.logout();
+        checkLoggedOut(salesPost2ServletPage, testRealmSAMLPostLoginPage);
+    }
+
+    @Test
+    public void salesPostAssertionAndResponseSigTest() {
+        testSuccessfulAndUnauthorizedLogin(salesPostAssertionAndResponseSigPage, testRealmSAMLPostLoginPage);
+    }
+
+    @Test
+    public void testPostBadAssertionSignature() {
+        badAssertionSalesPostSigPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login("bburke", "password");
+
+        waitUntilElement(By.xpath("//body")).text().contains("Error info: SamlAuthenticationError [reason=INVALID_SIGNATURE, status=null]");
+        assertEquals(driver.getCurrentUrl(), badAssertionSalesPostSigPage + "/saml");
+    }
+
+    @Test
+    public void testMissingAssertionSignature() {
+        missingAssertionSigPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login("bburke", "password");
+
+        waitUntilElement(By.xpath("//body")).text().contains("Error info: SamlAuthenticationError [reason=INVALID_SIGNATURE, status=null]");
+        assertEquals(driver.getCurrentUrl(), missingAssertionSigPage + "/saml");
+    }
+
+    @Test
+    public void testErrorHandling() throws Exception {
+        Client client = ClientBuilder.newClient();
+        // make sure
+        Response response = client.target(employeeSigServletPage.toString()).request().get();
+        response.close();
+        SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder()
+                .destination(employeeSigServletPage.toString() + "/saml")
+                .issuer("http://localhost:" + System.getProperty("auth.server.http.port", "8180") + "/realms/demo")
+                .status(JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get());
+        BaseSAML2BindingBuilder binding = new BaseSAML2BindingBuilder()
+                .relayState(null);
+        Document document = builder.buildDocument();
+        URI uri = binding.redirectBinding(document).generateURI(employeeSigServletPage.toString() + "/saml", false);
+        response = client.target(uri).request().get();
+        String errorPage = response.readEntity(String.class);
+        response.close();
+        Assert.assertTrue(errorPage.contains("Error info: SamlAuthenticationError [reason=ERROR_STATUS"));
+        Assert.assertFalse(errorPage.contains("status=null"));
+        client.close();
+    }
+
+    @Test
+    public void testRelayStateEncoding() throws Exception {
+        // this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
+        // at the relay state
+        employeeServletPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login("bburke", "password");
+        assertCurrentUrlStartsWith(employeeServletPage);
+        waitUntilElement(By.xpath("//body")).text().contains("Relay state: " + SamlSPFacade.RELAY_STATE);
+        waitUntilElement(By.xpath("//body")).text().not().contains("SAML response: null");
+    }
+
+    @Test
+    public void testAttributes() throws Exception {
+        ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "http://localhost:8081/employee2/");
+        ProtocolMappersResource protocolMappersResource = clientResource.getProtocolMappers();
+
+        Map<String, String> config = new LinkedHashMap<>();
+        config.put("attribute.nameformat", "Basic");
+        config.put("user.attribute", "topAttribute");
+        config.put("attribute.name", "topAttribute");
+        createProtocolMapper(protocolMappersResource, "topAttribute", "saml", "saml-user-attribute-mapper", config);
+
+        config = new LinkedHashMap<>();
+        config.put("attribute.nameformat", "Basic");
+        config.put("user.attribute", "level2Attribute");
+        config.put("attribute.name", "level2Attribute");
+        createProtocolMapper(protocolMappersResource, "level2Attribute", "saml", "saml-user-attribute-mapper", config);
+
+        config = new LinkedHashMap<>();
+        config.put("attribute.nameformat", "Basic");
+        config.put("single", "true");
+        config.put("attribute.name", "group");
+        createProtocolMapper(protocolMappersResource, "groups", "saml", "saml-group-membership-mapper", config);
+
+        setRolesToCheck("manager,user");
+
+        employee2ServletPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login("level2GroupUser", "password");
+
+        driver.navigate().to(employee2ServletPage.toString() + "/getAttributes");
+        waitUntilElement(By.xpath("//body")).text().contains("topAttribute: true");
+        waitUntilElement(By.xpath("//body")).text().contains("level2Attribute: true");
+        waitUntilElement(By.xpath("//body")).text().contains("attribute email: level2@redhat.com");
+        waitUntilElement(By.xpath("//body")).text().not().contains("group: []");
+        waitUntilElement(By.xpath("//body")).text().not().contains("group: null");
+        waitUntilElement(By.xpath("//body")).text().contains("group: [level2]");
+
+        employee2ServletPage.logout();
+        checkLoggedOut(employee2ServletPage, testRealmSAMLPostLoginPage);
+
+        setRolesToCheck("manager,employee,user");
+
+        employee2ServletPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login(bburkeUser);
+
+        driver.navigate().to(employee2ServletPage.toString() + "/getAttributes");
+        waitUntilElement(By.xpath("//body")).text().contains("attribute email: bburke@redhat.com");
+        waitUntilElement(By.xpath("//body")).text().contains("friendlyAttribute email: bburke@redhat.com");
+        waitUntilElement(By.xpath("//body")).text().contains("phone: 617");
+        waitUntilElement(By.xpath("//body")).text().contains("friendlyAttribute phone: null");
+
+        employee2ServletPage.logout();
+        checkLoggedOut(employee2ServletPage, testRealmSAMLPostLoginPage);
+
+        config = new LinkedHashMap<>();
+        config.put("attribute.value", "hard");
+        config.put("attribute.nameformat", "Basic");
+        config.put("attribute.name", "hardcoded-attribute");
+        createProtocolMapper(protocolMappersResource, "hardcoded-attribute", "saml", "saml-hardcode-attribute-mapper", config);
+
+        config = new LinkedHashMap<>();
+        config.put("role", "hardcoded-role");
+        createProtocolMapper(protocolMappersResource, "hardcoded-role", "saml", "saml-hardcode-role-mapper", config);
+
+        config = new LinkedHashMap<>();
+        config.put("new.role.name", "pee-on");
+        config.put("role", "http://localhost:8081/employee/.employee");
+        createProtocolMapper(protocolMappersResource, "renamed-employee-role", "saml", "saml-role-name-mapper", config);
+
+        for (ProtocolMapperRepresentation mapper : clientResource.toRepresentation().getProtocolMappers()) {
+            if (mapper.getName().equals("role-list")) {
+                protocolMappersResource.delete(mapper.getId());
+
+                mapper.setId(null);
+                mapper.getConfig().put(RoleListMapper.SINGLE_ROLE_ATTRIBUTE, "true");
+                mapper.getConfig().put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "memberOf");
+                protocolMappersResource.createMapper(mapper);
+            }
+        }
+
+        setRolesToCheck("pee-on,el-jefe,manager,hardcoded-role");
+
+        config = new LinkedHashMap<>();
+        config.put("new.role.name", "el-jefe");
+        config.put("role", "user");
+        createProtocolMapper(protocolMappersResource, "renamed-role", "saml", "saml-role-name-mapper", config);
+
+        employee2ServletPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login(bburkeUser);
+
+        driver.navigate().to(employee2ServletPage.toString() + "/getAttributes");
+        waitUntilElement(By.xpath("//body")).text().contains("hardcoded-attribute: hard");
+        employee2ServletPage.checkRolesEndPoint(false);
+        employee2ServletPage.logout();
+        checkLoggedOut(employee2ServletPage, testRealmSAMLPostLoginPage);
+    }
+
+    private void createProtocolMapper(ProtocolMappersResource resource, String name, String protocol, String protocolMapper, Map<String, String> config) {
+        ProtocolMapperRepresentation representation = new ProtocolMapperRepresentation();
+        representation.setName(name);
+        representation.setProtocol(protocol);
+        representation.setProtocolMapper(protocolMapper);
+        representation.setConfig(config);
+        resource.createMapper(representation);
+    }
+
+    private void setRolesToCheck(String roles) {
+        employee2ServletPage.navigateTo();
+        assertCurrentUrlStartsWith(testRealmSAMLPostLoginPage);
+        testRealmSAMLPostLoginPage.form().login(bburkeUser);
+        driver.navigate().to(employee2ServletPage.toString() + "/setCheckRoles?roles=" + roles);
         employee2ServletPage.logout();
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
index ee06750..b6f9bde 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
@@ -33,16 +33,14 @@ import org.keycloak.representations.adapters.action.PushNotBeforeAction;
 import org.keycloak.representations.adapters.action.TestAvailabilityAction;
 import org.keycloak.representations.idm.*;
 
+import javax.ws.rs.BadRequestException;
 import javax.ws.rs.NotFoundException;
 import javax.ws.rs.core.Response;
 
 import java.io.IOException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
+import org.keycloak.services.ErrorResponseException;
 import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.util.AdminEventPaths;
 import org.keycloak.testsuite.util.ClientBuilder;
@@ -212,6 +210,52 @@ public class ClientTest extends AbstractAdminTest {
         assertEquals("service-account-serviceclient", userRep.getUsername());
     }
 
+    // KEYCLOAK-3421
+    @Test
+    public void createClientWithFragments() {
+        ClientRepresentation client = ClientBuilder.create()
+                .clientId("client-with-fragment")
+                .rootUrl("http://localhost/base#someFragment")
+                .redirectUris("http://localhost/auth", "http://localhost/auth#fragment", "http://localhost/auth*", "/relative")
+                .build();
+
+        Response response = realm.clients().create(client);
+        assertUriFragmentError(response);
+    }
+
+    // KEYCLOAK-3421
+    @Test
+    public void updateClientWithFragments() {
+        ClientRepresentation client = ClientBuilder.create()
+                .clientId("client-with-fragment")
+                .redirectUris("http://localhost/auth", "http://localhost/auth*")
+                .build();
+        Response response = realm.clients().create(client);
+        ClientResource clientResource = realm.clients().get(ApiUtil.getCreatedId(response));
+
+        client = clientResource.toRepresentation();
+        client.setRootUrl("http://localhost/base#someFragment");
+        List<String> redirectUris = client.getRedirectUris();
+        redirectUris.add("http://localhost/auth#fragment");
+        redirectUris.add("/relative");
+        client.setRedirectUris(redirectUris);
+
+        try {
+            clientResource.update(client);
+            fail("Should fail");
+        }
+        catch (BadRequestException e) {
+            assertUriFragmentError(e.getResponse());
+        }
+    }
+
+    private void assertUriFragmentError(Response response) {
+        assertEquals(response.getStatus(), 400);
+        String error = response.readEntity(OAuth2ErrorRepresentation.class).getError();
+        assertTrue("Error response doesn't mention Redirect URIs fragments", error.contains("Redirect URIs must not contain an URI fragment"));
+        assertTrue("Error response doesn't mention Root URL fragments", error.contains("Root URL must not contain an URL fragment"));
+    }
+
     @Test
     public void pushRevocation() {
         testingClient.testApp().clearAdminActions();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
index 5d7d2c1..19d6413 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
@@ -35,24 +35,34 @@ import org.keycloak.common.util.CollectionUtil;
 import org.keycloak.common.util.KeycloakUriBuilder;
 import org.keycloak.constants.ServiceUrlConstants;
 import org.keycloak.jose.jwk.JSONWebKeySet;
+import org.keycloak.jose.jws.Algorithm;
 import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
+import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.protocol.oidc.utils.OIDCResponseType;
 import org.keycloak.representations.AccessToken;
+import org.keycloak.representations.JsonWebToken;
 import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
 import org.keycloak.representations.idm.ClientInitialAccessPresentation;
 import org.keycloak.representations.idm.ClientRegistrationTrustedHostRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.oidc.OIDCClientRepresentation;
 import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
+import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
+import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
 import org.keycloak.testsuite.util.OAuthClient;
 import java.security.PrivateKey;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
 
 import static org.junit.Assert.*;
 import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
@@ -96,24 +106,34 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         return response;
     }
 
-    @Test
-    public void testCreateWithTrustedHost() throws Exception {
-        reg.auth(null);
-
-        OIDCClientRepresentation client = createRep();
+    private void assertCreateFail(OIDCClientRepresentation client, int expectedStatusCode) {
+        assertCreateFail(client, expectedStatusCode, null);
+    }
 
-        // Failed to create client
+    private void assertCreateFail(OIDCClientRepresentation client, int expectedStatusCode, String expectedErrorContains) {
         try {
             reg.oidc().create(client);
             Assert.fail("Not expected to successfuly register client");
         } catch (ClientRegistrationException expected) {
             HttpErrorException httpEx = (HttpErrorException) expected.getCause();
-            Assert.assertEquals(401, httpEx.getStatusLine().getStatusCode());
+            Assert.assertEquals(expectedStatusCode, httpEx.getStatusLine().getStatusCode());
+            if (expectedErrorContains != null) {
+                assertTrue("Error response doesn't contain expected text", httpEx.getErrorResponse().contains(expectedErrorContains));
+            }
         }
+    }
+
+    @Test
+    public void testCreateWithTrustedHost() throws Exception {
+        reg.auth(null);
+
+        OIDCClientRepresentation client = createRep();
+
+        // Failed to create client
+        assertCreateFail(client, 401);
 
         // Create trusted host entry
-        Response response = adminClient.realm(REALM_NAME).clientRegistrationTrustedHost().create(ClientRegistrationTrustedHostRepresentation.create("localhost", 2, 2));
-        Assert.assertEquals(201, response.getStatus());
+        createTrustedHost("localhost", 2);
 
         // Successfully register client
         reg.oidc().create(client);
@@ -126,13 +146,20 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         reg.oidc().create(client);
 
         // Failed to create 3rd client
-        try {
-            reg.oidc().create(client);
-            Assert.fail("Not expected to successfuly register client");
-        } catch (ClientRegistrationException expected) {
-            HttpErrorException httpEx = (HttpErrorException) expected.getCause();
-            Assert.assertEquals(401, httpEx.getStatusLine().getStatusCode());
-        }
+        assertCreateFail(client, 401);
+    }
+
+    // KEYCLOAK-3421
+    @Test
+    public void createClientWithUriFragment() {
+        reg.auth(null);
+
+        createTrustedHost("localhost", 1);
+
+        OIDCClientRepresentation client = createRep();
+        client.setRedirectUris(Arrays.asList("http://localhost/auth", "http://localhost/auth#fragment", "http://localhost/auth*"));
+
+        assertCreateFail(client, 400, "URI fragment");
     }
 
     @Test
@@ -152,6 +179,7 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         assertEquals(Arrays.asList("code", "none"), response.getResponseTypes());
         assertEquals(Arrays.asList(OAuth2Constants.AUTHORIZATION_CODE, OAuth2Constants.REFRESH_TOKEN), response.getGrantTypes());
         assertEquals(OIDCLoginProtocol.CLIENT_SECRET_BASIC, response.getTokenEndpointAuthMethod());
+        Assert.assertNull(response.getUserinfoSignedResponseAlg());
     }
 
     @Test
@@ -212,8 +240,11 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         clientRep.setGrantTypes(Collections.singletonList(OAuth2Constants.CLIENT_CREDENTIALS));
         clientRep.setTokenEndpointAuthMethod(OIDCLoginProtocol.PRIVATE_KEY_JWT);
 
-        // Corresponds to PRIVATE_KEY
-        JSONWebKeySet keySet = loadJson(getClass().getResourceAsStream("/clientreg-test/jwks.json"), JSONWebKeySet.class);
+        // Generate keys for client
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+        Map<String, String> generatedKeys = oidcClientEndpointsResource.generateKeys();
+
+        JSONWebKeySet keySet = oidcClientEndpointsResource.getJwks();
         clientRep.setJwks(keySet);
 
         OIDCClientRepresentation response = reg.oidc().create(clientRep);
@@ -222,7 +253,7 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         Assert.assertNull(response.getClientSecretExpiresAt());
 
         // Tries to authenticate client with privateKey JWT
-        String signedJwt = getClientSignedJWT(response.getClientId());
+        String signedJwt = getClientSignedJWT(response.getClientId(), generatedKeys.get(TestingOIDCEndpointsApplicationResource.PRIVATE_KEY));
         OAuthClient.AccessTokenResponse accessTokenResponse = doClientCredentialsGrantRequest(signedJwt);
         Assert.assertEquals(200, accessTokenResponse.getStatusCode());
         AccessToken accessToken = oauth.verifyToken(accessTokenResponse.getAccessToken());
@@ -236,8 +267,11 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         clientRep.setGrantTypes(Collections.singletonList(OAuth2Constants.CLIENT_CREDENTIALS));
         clientRep.setTokenEndpointAuthMethod(OIDCLoginProtocol.PRIVATE_KEY_JWT);
 
-        // Use the realmKey for client authentication too
-        clientRep.setJwksUri(oauth.getCertsUrl(REALM_NAME));
+        // Generate keys for client
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+        Map<String, String> generatedKeys = oidcClientEndpointsResource.generateKeys();
+
+        clientRep.setJwksUri(TestApplicationResourceUrls.clientJwksUri());
 
         OIDCClientRepresentation response = reg.oidc().create(clientRep);
         Assert.assertEquals(OIDCLoginProtocol.PRIVATE_KEY_JWT, response.getTokenEndpointAuthMethod());
@@ -245,22 +279,51 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         Assert.assertNull(response.getClientSecretExpiresAt());
 
         // Tries to authenticate client with privateKey JWT
-        String signedJwt = getClientSignedJWT(response.getClientId());
+        String signedJwt = getClientSignedJWT(response.getClientId(), generatedKeys.get(TestingOIDCEndpointsApplicationResource.PRIVATE_KEY));
         OAuthClient.AccessTokenResponse accessTokenResponse = doClientCredentialsGrantRequest(signedJwt);
         Assert.assertEquals(200, accessTokenResponse.getStatusCode());
         AccessToken accessToken = oauth.verifyToken(accessTokenResponse.getAccessToken());
         Assert.assertEquals(response.getClientId(), accessToken.getAudience()[0]);
     }
 
+    @Test
+    public void testSignaturesRequired() throws Exception {
+        OIDCClientRepresentation clientRep = createRep();
+        clientRep.setUserinfoSignedResponseAlg(Algorithm.RS256.toString());
+        clientRep.setRequestObjectSigningAlg(Algorithm.RS256.toString());
+
+        OIDCClientRepresentation response = reg.oidc().create(clientRep);
+        Assert.assertEquals(Algorithm.RS256.toString(), response.getUserinfoSignedResponseAlg());
+        Assert.assertEquals(Algorithm.RS256.toString(), response.getRequestObjectSigningAlg());
+        Assert.assertNotNull(response.getClientSecret());
+
+        // Test Keycloak representation
+        ClientRepresentation kcClient = getClient(response.getClientId());
+        OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
+        Assert.assertEquals(config.getUserInfoSignedResponseAlg(), Algorithm.RS256);
+        Assert.assertEquals(config.getRequestObjectSignatureAlg(), Algorithm.RS256);
+    }
+
 
     // Client auth with signedJWT - helper methods
 
-    private String getClientSignedJWT(String clientId) {
+    private String getClientSignedJWT(String clientId, String privateKeyPem) {
         String realmInfoUrl = KeycloakUriBuilder.fromUri(getAuthServerRoot()).path(ServiceUrlConstants.REALM_INFO_PATH).build(REALM_NAME).toString();
 
-        PrivateKey privateKey = KeycloakModelUtils.getPrivateKey(PRIVATE_KEY);
+        PrivateKey privateKey = KeycloakModelUtils.getPrivateKey(privateKeyPem);
 
-        JWTClientCredentialsProvider jwtProvider = new JWTClientCredentialsProvider();
+        // Use token-endpoint as audience as OIDC conformance testsuite is using it too.
+        JWTClientCredentialsProvider jwtProvider = new JWTClientCredentialsProvider() {
+
+            @Override
+            protected JsonWebToken createRequestToken(String clientId, String realmInfoUrl) {
+                JsonWebToken jwt = super.createRequestToken(clientId, realmInfoUrl);
+                String tokenEndpointUrl = OIDCLoginProtocolService.tokenUrl(UriBuilder.fromUri(getAuthServerRoot())).build(REALM_NAME).toString();
+                jwt.audience(tokenEndpointUrl);
+                return jwt;
+            }
+
+        };
         jwtProvider.setPrivateKey(privateKey);
         jwtProvider.setTokenTimeout(10);
         return jwtProvider.createSignedRequestToken(clientId, realmInfoUrl);
@@ -290,4 +353,9 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
         }
     }
 
+    private void createTrustedHost(String name, int count) {
+        Response response = adminClient.realm(REALM_NAME).clientRegistrationTrustedHost().create(ClientRegistrationTrustedHostRepresentation.create(name, count, count));
+        Assert.assertEquals(201, response.getStatus());
+    }
+
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java
index 6abaf97..43c6fa9 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportTest.java
@@ -75,11 +75,11 @@ public class ExportImportTest extends AbstractExportImportTest {
 
     @Test
     public void testDirFullExportImport() throws Throwable {
-        testingClient.testing().setProvider(DirExportProviderFactory.PROVIDER_ID);
-        String targetDirPath = testingClient.testing().getExportImportTestDirectory()+ File.separator + "dirExport";
+        testingClient.testing().exportImport().setProvider(DirExportProviderFactory.PROVIDER_ID);
+        String targetDirPath = testingClient.testing().exportImport().getExportImportTestDirectory()+ File.separator + "dirExport";
         DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
-        testingClient.testing().setDir(targetDirPath);
-        testingClient.testing().setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
+        testingClient.testing().exportImport().setDir(targetDirPath);
+        testingClient.testing().exportImport().setUsersPerFile(ExportImportConfig.DEFAULT_USERS_PER_FILE);
 
         testFullExportImport();
 
@@ -89,11 +89,13 @@ public class ExportImportTest extends AbstractExportImportTest {
 
     @Test
     public void testDirRealmExportImport() throws Throwable {
-        testingClient.testing().setProvider(DirExportProviderFactory.PROVIDER_ID);
-        String targetDirPath = testingClient.testing().getExportImportTestDirectory() + File.separator + "dirRealmExport";
+        testingClient.testing()
+                .exportImport()
+                .setProvider(DirExportProviderFactory.PROVIDER_ID);
+        String targetDirPath = testingClient.testing().exportImport().getExportImportTestDirectory() + File.separator + "dirRealmExport";
         DirExportProvider.recursiveDeleteDir(new File(targetDirPath));
-        testingClient.testing().setDir(targetDirPath);
-        testingClient.testing().setUsersPerFile(3);
+        testingClient.testing().exportImport().setDir(targetDirPath);
+        testingClient.testing().exportImport().setUsersPerFile(3);
 
         testRealmExportImport();
 
@@ -104,18 +106,18 @@ public class ExportImportTest extends AbstractExportImportTest {
 
     @Test
     public void testSingleFileFullExportImport() throws Throwable {
-        testingClient.testing().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
-        String targetFilePath = testingClient.testing().getExportImportTestDirectory() + File.separator + "singleFile-full.json";
-        testingClient.testing().setFile(targetFilePath);
+        testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        String targetFilePath = testingClient.testing().exportImport().getExportImportTestDirectory() + File.separator + "singleFile-full.json";
+        testingClient.testing().exportImport().setFile(targetFilePath);
 
         testFullExportImport();
     }
 
     @Test
     public void testSingleFileRealmExportImport() throws Throwable {
-        testingClient.testing().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
-        String targetFilePath = testingClient.testing().getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
-        testingClient.testing().setFile(targetFilePath);
+        testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        String targetFilePath = testingClient.testing().exportImport().getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
+        testingClient.testing().exportImport().setFile(targetFilePath);
 
         testRealmExportImport();
     }
@@ -126,14 +128,14 @@ public class ExportImportTest extends AbstractExportImportTest {
         removeRealm("test-realm");
 
         // Set the realm, which doesn't have builtin clients/roles inside JSON
-        testingClient.testing().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
         URL url = ExportImportTest.class.getResource("/model/testrealm.json");
         String targetFilePath = new File(url.getFile()).getAbsolutePath();
-        testingClient.testing().setFile(targetFilePath);
+        testingClient.testing().exportImport().setFile(targetFilePath);
 
-        testingClient.testing().setAction(ExportImportConfig.ACTION_IMPORT);
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_IMPORT);
 
-        testingClient.testing().runImport();
+        testingClient.testing().exportImport().runImport();
 
         RealmResource testRealmRealm = adminClient.realm("test-realm");
 
@@ -158,14 +160,14 @@ public class ExportImportTest extends AbstractExportImportTest {
         realm.components().add(component);
 
 
-        testingClient.testing().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
+        testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
 
-        String targetFilePath = testingClient.testing().getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
-        testingClient.testing().setFile(targetFilePath);
-        testingClient.testing().setAction(ExportImportConfig.ACTION_EXPORT);
-        testingClient.testing().setRealmName("component-realm");
+        String targetFilePath = testingClient.testing().exportImport().getExportImportTestDirectory() + File.separator + "singleFile-realm.json";
+        testingClient.testing().exportImport().setFile(targetFilePath);
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_EXPORT);
+        testingClient.testing().exportImport().setRealmName("component-realm");
 
-        testingClient.testing().runExport();
+        testingClient.testing().exportImport().runExport();
 
         // Delete some realm (and some data in admin realm)
         adminClient.realm("component-realm").remove();
@@ -173,9 +175,9 @@ public class ExportImportTest extends AbstractExportImportTest {
         Assert.assertEquals(3, adminClient.realms().findAll().size());
 
         // Configure import
-        testingClient.testing().setAction(ExportImportConfig.ACTION_IMPORT);
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_IMPORT);
 
-        testingClient.testing().runImport();
+        testingClient.testing().exportImport().runImport();
 
         realmRep = realm.toRepresentation();
 
@@ -203,10 +205,10 @@ public class ExportImportTest extends AbstractExportImportTest {
     }
 
     private void testFullExportImport() throws LifecycleException {
-        testingClient.testing().setAction(ExportImportConfig.ACTION_EXPORT);
-        testingClient.testing().setRealmName("");
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_EXPORT);
+        testingClient.testing().exportImport().setRealmName("");
 
-        testingClient.testing().runExport();
+        testingClient.testing().exportImport().runExport();
 
         removeRealm("test");
         removeRealm("test-realm");
@@ -218,9 +220,9 @@ public class ExportImportTest extends AbstractExportImportTest {
         assertNotAuthenticated("test", "user3", "password");
 
         // Configure import
-        testingClient.testing().setAction(ExportImportConfig.ACTION_IMPORT);
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_IMPORT);
 
-        testingClient.testing().runImport();
+        testingClient.testing().exportImport().runImport();
 
         // Ensure data are imported back
         Assert.assertEquals(3, adminClient.realms().findAll().size());
@@ -232,10 +234,10 @@ public class ExportImportTest extends AbstractExportImportTest {
     }
 
     private void testRealmExportImport() throws LifecycleException {
-        testingClient.testing().setAction(ExportImportConfig.ACTION_EXPORT);
-        testingClient.testing().setRealmName("test");
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_EXPORT);
+        testingClient.testing().exportImport().setRealmName("test");
 
-        testingClient.testing().runExport();
+        testingClient.testing().exportImport().runExport();
 
         // Delete some realm (and some data in admin realm)
         adminClient.realm("test").remove();
@@ -248,9 +250,9 @@ public class ExportImportTest extends AbstractExportImportTest {
         assertNotAuthenticated("test", "user3", "password");
 
         // Configure import
-        testingClient.testing().setAction(ExportImportConfig.ACTION_IMPORT);
+        testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_IMPORT);
 
-        testingClient.testing().runImport();
+        testingClient.testing().exportImport().runImport();
 
         // Ensure data are imported back, but just for "test" realm
         Assert.assertEquals(3, adminClient.realms().findAll().size());
@@ -273,27 +275,4 @@ public class ExportImportTest extends AbstractExportImportTest {
         Assert.assertEquals(expectedResult, testingClient.testing().validCredentials(realmName, username, password));
     }
 
-    private static String getExportImportTestDirectory() {
-        String dirPath = null;
-        String relativeDirExportImportPath = "testsuite" + File.separator +
-                                             "integration-arquillian" + File.separator +
-                                             "tests" + File.separator +
-                                             "base" + File.separator +
-                                             "target" + File.separator +
-                                             "export-import";
-
-        if (System.getProperties().containsKey("maven.home")) {
-            dirPath = System.getProperty("user.dir").replaceFirst("testsuite.integration.*", Matcher.quoteReplacement(relativeDirExportImportPath));
-        } else {
-            for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
-                if (c.contains(File.separator + "testsuite" + File.separator + "integration-arquillian" + File.separator)) {
-                    dirPath = c.replaceFirst("testsuite.integration-arquillian.*", Matcher.quoteReplacement(relativeDirExportImportPath));
-                }
-            }
-        }
-
-        String absolutePath = new File(dirPath).getAbsolutePath();
-        return absolutePath;
-    }
-
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
index 78d4faa..1864324 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/migration/MigrationTest.java
@@ -17,69 +17,52 @@
 package org.keycloak.testsuite.migration;
 
 import java.util.List;
-import static org.junit.Assert.*;
-import org.junit.Ignore;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
-import org.keycloak.admin.client.resource.ClientsResource;
 import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.arquillian.migration.Migration;
 
 /**
  * @author <a href="mailto:vramik@redhat.com">Vlastislav Ramik</a>
  */
 public class MigrationTest extends AbstractKeycloakTest {
-    
+
+    private RealmResource realmResource;
+    private RealmRepresentation realmRep;
+        
     @Override
     public void addTestRealms(List<RealmRepresentation> testRealms) {
         log.info("Adding no test realms for migration test. Test realm should be migrated from previous vesrion.");
     }
     
-    @Test
-    @Migration(versionFrom = "1.6.1.Final")
-    public void migration16Test() {
-        RealmResource realmResource = adminClient.realms().realm("Migration");
-        RealmRepresentation realmRep = realmResource.toRepresentation();
-        assertEquals("Migration", realmRep.getRealm());
-        
-        List<RoleRepresentation> realmRoles = realmResource.roles().list();
-        assertEquals(1, realmRoles.size());
-        assertEquals("offline_access", realmRoles.get(0).getName());
-        
-        for (ClientRepresentation client : realmResource.clients().findAll()) {
-            final String clientId = client.getClientId();
-            switch (clientId) {
-                case "realm-management":
-                    assertEquals(13, realmResource.clients().get(client.getId()).roles().list().size());
-                    break;
-                case "security-admin-console":
-                    assertEquals(0, realmResource.clients().get(client.getId()).roles().list().size());
-                    break;
-                case "broker":
-                    assertEquals(1, realmResource.clients().get(client.getId()).roles().list().size());
-                    break;
-                case "account":
-                    assertEquals(2, realmResource.clients().get(client.getId()).roles().list().size());
-                    break;
-                default:
-                    fail("Migrated realm contains unexpected client " + clientId);
-                    break;
-            }
-        }
+    @Before
+    public void beforeMigrationTest() {
+        realmResource = adminClient.realms().realm("Migration");
+        realmRep = realmResource.toRepresentation();
     }
     
     @Test
-    @Migration(versionFrom = "1.5.1.Final")
-    @Ignore
-    public void migration15Test() {
-        for (RealmRepresentation realm : adminClient.realms().findAll()) {
-            System.out.println(realm.getRealm());
-        }
+    @Migration(versionFrom = "1.9.8.Final")
+    public void migration198Test() {
+        Assert.assertNames(realmResource.roles().list(), "offline_access", "uma_authorization");
+        Assert.assertNames(realmResource.clients().findAll(), "admin-cli", "realm-management", "security-admin-console", "broker", "account");
         
         //TODO
     }
-
+    
+    /**
+     * Assumed that there is only one migration test for each version and *remove*
+     * 'Migration' realm from Keycloak after test to be able to run the rest 
+     * of the testsuite isolated afterward.
+     */
+    @After
+    public void afterMigrationTest() {
+        log.info("removing '" + realmRep.getRealm() + "' realm");
+        removeRealm(realmRep);
+    }
+    
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java
index 087a1e6..c1cbdea 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ClientAuthSignedJWTTest.java
@@ -55,7 +55,9 @@ import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.util.CertificateInfoHelper;
 import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.admin.ApiUtil;
 import org.keycloak.testsuite.auth.page.AuthRealm;
@@ -70,6 +72,7 @@ import java.net.URL;
 import java.nio.file.Files;
 import java.security.KeyStore;
 import java.security.PrivateKey;
+import java.security.PublicKey;
 import java.security.cert.X509Certificate;
 import java.util.*;
 
@@ -81,7 +84,6 @@ import static org.junit.Assert.assertNotEquals;
  * @author Vaclav Muzikar <vmuzikar@redhat.com>
  */
 public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
-    public static final String CERTIFICATE_PEM = "Certificate PEM";
 
     @Rule
     public AssertEvents events = new AssertEvents(this);
@@ -349,8 +351,18 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
     }
 
     @Test
-    public void testUploadPEM() throws Exception {
-        testUploadKeystore(CERTIFICATE_PEM, "client-auth-test/certificate.pem", "undefined", "undefined");
+    public void testUploadCertificatePEM() throws Exception {
+        testUploadKeystore(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.CERTIFICATE_PEM, "client-auth-test/certificate.pem", "undefined", "undefined");
+    }
+
+    @Test
+    public void testUploadPublicKeyPEM() throws Exception {
+        testUploadKeystore(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.PUBLIC_KEY_PEM, "client-auth-test/publickey.pem", "undefined", "undefined");
+    }
+
+    @Test
+    public void testUploadJWKS() throws Exception {
+        testUploadKeystore(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.JSON_WEB_KEY_SET, "clientreg-test/jwks.json", "undefined", "undefined");
     }
 
     // We need to test this as a genuine REST API HTTP request
@@ -395,20 +407,27 @@ public class ClientAuthSignedJWTTest extends AbstractKeycloakTest {
         assertEquals(200, httpResponse.getStatusLine().getStatusCode());
 
         client = getClient(testRealm.getRealm(), client.getId()).toRepresentation();
-        String pem;
 
         // Assert the uploaded certificate
-        if (!keystoreFormat.equals(CERTIFICATE_PEM)) {
+        if (keystoreFormat.equals(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.PUBLIC_KEY_PEM)) {
+            String pem = new String(Files.readAllBytes(keystoreFile.toPath()));
+            final String publicKeyNew = client.getAttributes().get(JWTClientAuthenticator.ATTR_PREFIX + "." + CertificateInfoHelper.PUBLIC_KEY);
+            assertEquals("Certificates don't match", pem, publicKeyNew);
+        } else if (keystoreFormat.equals(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.JSON_WEB_KEY_SET)) {
+            final String publicKeyNew = client.getAttributes().get(JWTClientAuthenticator.ATTR_PREFIX + "." + CertificateInfoHelper.PUBLIC_KEY);
+            // Just assert it's valid public key
+            PublicKey pk = KeycloakModelUtils.getPublicKey(publicKeyNew);
+            Assert.assertNotNull(pk);
+        } else if (keystoreFormat.equals(org.keycloak.services.resources.admin.ClientAttributeCertificateResource.CERTIFICATE_PEM)) {
+            String pem = new String(Files.readAllBytes(keystoreFile.toPath()));
+            assertCertificate(client, certOld, pem);
+        } else {
             InputStream keystoreIs = new FileInputStream(keystoreFile);
             KeyStore keyStore = getKeystore(keystoreIs, storePassword, keystoreFormat);
             keystoreIs.close();
-            pem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) keyStore.getCertificate(keyAlias));
+            String pem = KeycloakModelUtils.getPemFromCertificate((X509Certificate) keyStore.getCertificate(keyAlias));
+            assertCertificate(client, certOld, pem);
         }
-        else {
-            pem = new String(Files.readAllBytes(keystoreFile.toPath()));
-        }
-
-        assertCertificate(client, certOld, pem);
     }
 
     // TEST ERRORS
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
index f80e789..520f910 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
@@ -97,6 +97,11 @@ public class OAuthRedirectUriTest extends AbstractKeycloakTest {
                 .secret("password");
         realm.client(installedApp6);
 
+        ClientBuilder installedApp7 = ClientBuilder.create().id("test-query-component").name("test-query-component")
+                .redirectUris("http://localhost?foo=bar", "http://localhost?foo=bar*")
+                .secret("password");
+        realm.client(installedApp7);
+
         testRealms.add(realm.build());
     }
 
@@ -186,6 +191,26 @@ public class OAuthRedirectUriTest extends AbstractKeycloakTest {
     }
 
     @Test
+    public void testQueryComponents() throws IOException {
+        // KEYCLOAK-3420
+        oauth.clientId("test-query-component");
+        checkRedirectUri("http://localhost?foo=bar", true);
+        checkRedirectUri("http://localhost?foo=bara", false);
+        checkRedirectUri("http://localhost?foo=bar/", false);
+        checkRedirectUri("http://localhost?foo2=bar2&foo=bar", false);
+        checkRedirectUri("http://localhost?foo=b", false);
+        checkRedirectUri("http://localhost?foo", false);
+        checkRedirectUri("http://localhost?foo=bar&bar=foo", false);
+        checkRedirectUri("http://localhost?foo&bar=foo", false);
+        checkRedirectUri("http://localhost?foo&bar", false);
+        checkRedirectUri("http://localhost", false);
+
+        // KEYCLOAK-3418
+        oauth.clientId("test-installed");
+        checkRedirectUri("http://localhost?foo=bar", false);
+    }
+
+    @Test
     public void testWildcard() throws IOException {
         oauth.clientId("test-wildcard");
         checkRedirectUri("http://example.com", false);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
index 191581e..e01057d 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
@@ -19,30 +19,42 @@ package org.keycloak.testsuite.oidc;
 
 import java.util.List;
 
-
 import org.jboss.arquillian.graphene.page.Page;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuthErrorException;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
 import org.keycloak.common.util.Time;
 import org.keycloak.events.Details;
+import org.keycloak.jose.jws.Algorithm;
 import org.keycloak.models.Constants;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
 import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.CertificateRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.EventRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.util.CertificateInfoHelper;
 import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.AssertEvents;
 import org.keycloak.testsuite.TestRealmKeycloakTest;
 import org.keycloak.testsuite.admin.AbstractAdminTest;
+import org.keycloak.testsuite.admin.ApiUtil;
+import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
+import org.keycloak.testsuite.client.resources.TestOIDCEndpointsApplicationResource;
 import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
 import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.ErrorPage;
 import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.pages.OAuthGrantPage;
+import org.keycloak.testsuite.rest.resource.TestingOIDCEndpointsApplicationResource;
 import org.keycloak.testsuite.util.ClientManager;
 import org.keycloak.testsuite.util.OAuthClient;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -68,6 +80,9 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
     @Page
     protected OAuthGrantPage grantPage;
 
+    @Page
+    protected ErrorPage errorPage;
+
 
     @Override
     public void configureTestRealm(RealmRepresentation testRealm) {
@@ -308,29 +323,98 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
     // REQUEST & REQUEST_URI
 
     @Test
-    public void requestParam() {
-        driver.navigate().to(oauth.getLoginFormUrl() + "&request=abc");
+    public void requestParamUnsigned() throws Exception {
+        String validRedirectUri = oauth.getRedirectUri();
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
 
-        assertFalse(loginPage.isCurrent());
+        // Send request object with invalid redirect uri.
+        oidcClientEndpointsResource.setOIDCRequest("test", "test-app", "http://invalid", null, Algorithm.none.toString());
+        String requestStr = oidcClientEndpointsResource.getOIDCRequest();
+
+        oauth.request(requestStr);
+        oauth.openLoginForm();
+        Assert.assertTrue(errorPage.isCurrent());
+        assertEquals("Invalid parameter: redirect_uri", errorPage.getError());
+
+        // Assert the value from request object has bigger priority then from the query parameter.
+        oauth.redirectUri("http://invalid");
+        oidcClientEndpointsResource.setOIDCRequest("test", "test-app", validRedirectUri, "10", Algorithm.none.toString());
+        requestStr = oidcClientEndpointsResource.getOIDCRequest();
+
+        oauth.request(requestStr);
+        OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
+        Assert.assertNotNull(response.getCode());
+        Assert.assertEquals("mystate", response.getState());
         assertTrue(appPage.isCurrent());
+    }
 
-        // Assert error response was sent because not logged in
-        OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
-        Assert.assertNull(resp.getCode());
-        Assert.assertEquals(OAuthErrorException.REQUEST_NOT_SUPPORTED, resp.getError());
+    @Test
+    public void requestUriParamUnsigned() throws Exception {
+        String validRedirectUri = oauth.getRedirectUri();
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+
+        // Send request object with invalid redirect uri.
+        oidcClientEndpointsResource.setOIDCRequest("test", "test-app", "http://invalid", null, Algorithm.none.toString());
+
+        oauth.requestUri(TestApplicationResourceUrls.clientRequestUri());
+        oauth.openLoginForm();
+        Assert.assertTrue(errorPage.isCurrent());
+        assertEquals("Invalid parameter: redirect_uri", errorPage.getError());
+
+        // Assert the value from request object has bigger priority then from the query parameter.
+        oauth.redirectUri("http://invalid");
+        oidcClientEndpointsResource.setOIDCRequest("test", "test-app", validRedirectUri, "10", Algorithm.none.toString());
+
+        OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
+        Assert.assertNotNull(response.getCode());
+        Assert.assertEquals("mystate", response.getState());
+        assertTrue(appPage.isCurrent());
     }
 
     @Test
-    public void requestUriParam() {
-        driver.navigate().to(oauth.getLoginFormUrl() + "&request_uri=https%3A%2F%2Flocalhost%3A60784%2Fexport%2FqzHTG11W48.jwt");
+    public void requestUriParamSigned() throws Exception {
+        String validRedirectUri = oauth.getRedirectUri();
+        TestOIDCEndpointsApplicationResource oidcClientEndpointsResource = testingClient.testApp().oidcClientEndpoints();
+
+        // Set required signature for request_uri
+        ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
+        ClientRepresentation clientRep = clientResource.toRepresentation();
+        OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectSignatureAlg(Algorithm.RS256);
+        clientResource.update(clientRep);
+
+        // Verify unsigned request_uri will fail
+        oidcClientEndpointsResource.setOIDCRequest("test", "test-app", validRedirectUri, "10", Algorithm.none.toString());
+        oauth.requestUri(TestApplicationResourceUrls.clientRequestUri());
+        oauth.openLoginForm();
+        Assert.assertTrue(errorPage.isCurrent());
+        assertEquals("Invalid Request", errorPage.getError());
 
-        assertFalse(loginPage.isCurrent());
+        // Generate keypair for client
+        String clientPublicKeyPem = oidcClientEndpointsResource.generateKeys().get(TestingOIDCEndpointsApplicationResource.PUBLIC_KEY);
+
+        // Verify signed request_uri will fail due to failed signature validation
+        oidcClientEndpointsResource.setOIDCRequest("test", "test-app", validRedirectUri, "10", Algorithm.RS256.toString());
+        oauth.openLoginForm();
+        Assert.assertTrue(errorPage.isCurrent());
+        assertEquals("Invalid Request", errorPage.getError());
+
+
+        // Update clientModel with publicKey for signing
+        clientRep = clientResource.toRepresentation();
+        CertificateRepresentation cert = new CertificateRepresentation();
+        cert.setPublicKey(clientPublicKeyPem);
+        CertificateInfoHelper.updateClientRepresentationCertificateInfo(clientRep, cert, JWTClientAuthenticator.ATTR_PREFIX);
+        clientResource.update(clientRep);
+
+        // Check signed request_uri will pass
+        OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
+        Assert.assertNotNull(response.getCode());
+        Assert.assertEquals("mystate", response.getState());
         assertTrue(appPage.isCurrent());
 
-        // Assert error response was sent because not logged in
-        OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
-        Assert.assertNull(resp.getCode());
-        Assert.assertEquals(OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, resp.getError());
+        // Revert requiring signature for client
+        OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setRequestObjectSignatureAlg(null);
+        clientResource.update(clientRep);
     }
 
     // LOGIN_HINT
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java
index ab5c230..7fea657 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCWellKnownProviderTest.java
@@ -86,6 +86,8 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
 
             Assert.assertNames(oidcConfig.getSubjectTypesSupported(), "public");
             Assert.assertNames(oidcConfig.getIdTokenSigningAlgValuesSupported(), Algorithm.RS256.toString());
+            Assert.assertNames(oidcConfig.getUserInfoSigningAlgValuesSupported(), Algorithm.RS256.toString());
+            Assert.assertNames(oidcConfig.getRequestObjectSigningAlgValuesSupported(), Algorithm.none.toString(), Algorithm.RS256.toString());
 
             // Client authentication
             Assert.assertNames(oidcConfig.getTokenEndpointAuthMethodsSupported(), "client_secret_basic", "client_secret_post", "private_key_jwt");
@@ -100,8 +102,8 @@ public class OIDCWellKnownProviderTest extends AbstractKeycloakTest {
             Assert.assertNames(oidcConfig.getScopesSupported(), OAuth2Constants.SCOPE_OPENID, OAuth2Constants.OFFLINE_ACCESS);
 
             // Request and Request_Uri
-            Assert.assertFalse(oidcConfig.getRequestParameterSupported());
-            Assert.assertFalse(oidcConfig.getRequestUriParameterSupported());
+            Assert.assertTrue(oidcConfig.getRequestParameterSupported());
+            Assert.assertTrue(oidcConfig.getRequestUriParameterSupported());
         } finally {
             client.close();
         }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
index 268333f..e0588e7 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
@@ -21,19 +21,31 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
+import org.keycloak.admin.client.resource.ClientResource;
 import org.keycloak.events.Details;
 import org.keycloak.events.Errors;
 import org.keycloak.events.EventType;
+import org.keycloak.jose.jws.Algorithm;
+import org.keycloak.jose.jws.JWSInput;
+import org.keycloak.jose.jws.crypto.RSAProvider;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessTokenResponse;
 import org.keycloak.representations.UserInfo;
+import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.Urls;
 import org.keycloak.testsuite.AbstractKeycloakTest;
+import org.keycloak.testsuite.Assert;
 import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.admin.ApiUtil;
 import org.keycloak.testsuite.util.ClientManager;
 import org.keycloak.testsuite.util.RealmBuilder;
 import org.keycloak.testsuite.util.UserInfoClientUtil;
 import org.keycloak.util.BasicAuthHelper;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.utils.MediaType;
 
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
@@ -45,6 +57,7 @@ import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriBuilder;
 import java.net.URI;
+import java.security.PublicKey;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
@@ -153,6 +166,62 @@ public class UserInfoTest extends AbstractKeycloakTest {
     }
 
     @Test
+    public void testSuccessSignedResponse() throws Exception {
+        // Require signed userInfo request
+        ClientResource clientResource = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app");
+        ClientRepresentation clientRep = clientResource.toRepresentation();
+        OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setUserInfoSignedResponseAlg(Algorithm.RS256);
+        clientResource.update(clientRep);
+
+        // test signed response
+        Client client = ClientBuilder.newClient();
+
+        try {
+            AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(client);
+
+            Response response = UserInfoClientUtil.executeUserInfoRequest_getMethod(client, accessTokenResponse.getToken());
+
+            events.expect(EventType.USER_INFO_REQUEST)
+                    .session(Matchers.notNullValue(String.class))
+                    .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
+                    .detail(Details.USERNAME, "test-user@localhost")
+                    .detail(Details.SIGNATURE_REQUIRED, "true")
+                    .detail(Details.SIGNATURE_ALGORITHM, Algorithm.RS256.toString())
+                    .assertEvent();
+
+            // Check signature and content
+            RealmRepresentation realmRep = adminClient.realm("test").toRepresentation();
+            PublicKey publicKey = KeycloakModelUtils.getPublicKey(realmRep.getPublicKey());
+
+            Assert.assertEquals(200, response.getStatus());
+            Assert.assertEquals(response.getHeaderString(HttpHeaders.CONTENT_TYPE), MediaType.APPLICATION_JWT);
+            String signedResponse = response.readEntity(String.class);
+            response.close();
+
+            JWSInput jwsInput = new JWSInput(signedResponse);
+            Assert.assertTrue(RSAProvider.verify(jwsInput, publicKey));
+
+            UserInfo userInfo = JsonSerialization.readValue(jwsInput.getContent(), UserInfo.class);
+
+            Assert.assertNotNull(userInfo);
+            Assert.assertNotNull(userInfo.getSubject());
+            Assert.assertEquals("test-user@localhost", userInfo.getEmail());
+            Assert.assertEquals("test-user@localhost", userInfo.getPreferredUsername());
+
+            Assert.assertTrue(userInfo.hasAudience("test-app"));
+            String expectedIssuer = Urls.realmIssuer(new URI(AUTH_SERVER_ROOT), "test");
+            Assert.assertEquals(expectedIssuer, userInfo.getIssuer());
+
+        } finally {
+            client.close();
+        }
+
+        // Revert signed userInfo request
+        OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setUserInfoSignedResponseAlg(null);
+        clientResource.update(clientRep);
+    }
+
+    @Test
     public void testSessionExpired() throws Exception {
         Client client = ClientBuilder.newClient();
 
@@ -235,6 +304,7 @@ public class UserInfoTest extends AbstractKeycloakTest {
                 .session(Matchers.notNullValue(String.class))
                 .detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN)
                 .detail(Details.USERNAME, "test-user@localhost")
+                .detail(Details.SIGNATURE_REQUIRED, "false")
                 .assertEvent();
         UserInfoClientUtil.testSuccessfulUserInfoResponse(response, "test-user@localhost", "test-user@localhost");
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SslMailServer.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SslMailServer.java
index 0088e42..0f87d49 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SslMailServer.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/SslMailServer.java
@@ -91,7 +91,7 @@ public class SslMailServer {
             ksKeys.load(keyStoreIS, keyStorePassphrase);
 
             // KeyManager decides which key material to use.
-            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
             kmf.init(ksKeys, keyStorePassphrase);
 
             // Trust store for client authentication.
@@ -101,7 +101,7 @@ public class SslMailServer {
             ksTrust.load(trustStoreIS, trustStorePassphrase);
 
             // TrustManager decides which certificate authorities to use.
-            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
             tmf.init(ksTrust);
 
             final SSLContext sslContext = SSLContext.getInstance("TLS");
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/bad-assertion-sales-post-sig/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/bad-assertion-sales-post-sig/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..2ea7ff7
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/bad-assertion-sales-post-sig/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,62 @@
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/bad-assertion-sales-post-sig/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8081/bad-realm-sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8081/bad-realm-sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp">
+            <SingleSignOnService signRequest="true"
+                                 validateAssertionSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    validateRequestSignature="true"
+                    validateResponseSignature="true"
+                    signRequest="true"
+                    signResponse="true"
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/bad-assertion-sales-post-sig/WEB-INF/keystore.jks b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/bad-assertion-sales-post-sig/WEB-INF/keystore.jks
new file mode 100755
index 0000000..215384c
Binary files /dev/null and b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/bad-assertion-sales-post-sig/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..96f0b86
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,42 @@
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/employee/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="memberOf"/>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp">
+            <SingleSignOnService requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee/WEB-INF/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee/WEB-INF/web.xml
new file mode 100644
index 0000000..0199588
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/employee/WEB-INF/web.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+    <module-name>%CONTEXT_PATH%</module-name>
+
+    <servlet>
+        <servlet-name>Servlet</servlet-name>
+        <servlet-class>org.keycloak.testsuite.adapter.servlet.SamlSPFacade</servlet-class>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>Servlet</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Users</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>manager</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>KEYCLOAK-SAML</auth-method>
+        <realm-name>demo</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>manager</role-name>
+    </security-role>
+</web-app>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/input-portal/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/input-portal/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..e1cd76a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/input-portal/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,41 @@
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/input-portal/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp">
+            <SingleSignOnService requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/input-portal/WEB-INF/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/input-portal/WEB-INF/web.xml
new file mode 100644
index 0000000..865dc8a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/input-portal/WEB-INF/web.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+    <module-name>%CONTEXT_PATH%</module-name>
+
+    <servlet>
+        <servlet-name>Servlet</servlet-name>
+        <servlet-class>org.keycloak.testsuite.adapter.servlet.InputServlet</servlet-class>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>Servlet</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Users</web-resource-name>
+            <url-pattern>/secured/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>manager</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <login-config>
+        <auth-method>KEYCLOAK-SAML</auth-method>
+        <realm-name>demo</realm-name>
+    </login-config>
+
+    <security-role>
+        <role-name>manager</role-name>
+    </security-role>
+</web-app>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/missing-assertion-sig/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/missing-assertion-sig/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..936fb21
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/missing-assertion-sig/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,60 @@
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2016 Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/missing-assertion-sig/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp"
+             signaturesRequired="true">
+        <SingleSignOnService requestBinding="POST"
+                             bindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                             validateAssertionSignature="true"
+                             validateResponseSignature="false"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/missing-assertion-sig/WEB-INF/keystore.jks b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/missing-assertion-sig/WEB-INF/keystore.jks
new file mode 100755
index 0000000..144830b
Binary files /dev/null and b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/missing-assertion-sig/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post2/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post2/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..eae5b14
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post2/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,41 @@
+<!--
+  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+  ~ and other contributors as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post2/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp">
+            <SingleSignOnService requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post-assertion-and-response-sig/WEB-INF/keycloak-saml.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post-assertion-and-response-sig/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..94c3f4d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post-assertion-and-response-sig/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,60 @@
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright 2016 Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8081/sales-post-assertion-and-response-sig/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+        <Keys>
+            <Key signing="true" >
+                <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                    <PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
+                    <Certificate alias="http://localhost:8080/sales-post-sig/"/>
+                </KeyStore>
+            </Key>
+        </Keys>
+        <PrincipalNameMapping policy="FROM_NAME_ID"/>
+        <RoleIdentifiers>
+            <Attribute name="Role"/>
+        </RoleIdentifiers>
+        <IDP entityID="idp"
+             signaturesRequired="true">
+        <SingleSignOnService requestBinding="POST"
+                             bindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                             validateAssertionSignature="true"
+                             validateResponseSignature="true"
+                    />
+
+            <SingleLogoutService
+                    requestBinding="POST"
+                    responseBinding="POST"
+                    postBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    redirectBindingUrl="http://localhost:8080/auth/realms/demo/protocol/saml"
+                    />
+            <Keys>
+                <Key signing="true">
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <Certificate alias="demo"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+        </IDP>
+     </SP>
+</keycloak-saml-adapter>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post-assertion-and-response-sig/WEB-INF/keystore.jks b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post-assertion-and-response-sig/WEB-INF/keystore.jks
new file mode 100755
index 0000000..144830b
Binary files /dev/null and b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/sales-post-assertion-and-response-sig/WEB-INF/keystore.jks differ
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json
index 5a1d2c6..0e25d89 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/testsaml.json
@@ -68,6 +68,101 @@
     ],
     "clients": [
         {
+            "clientId": "http://localhost:8081/missing-assertion-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/missing-assertion-sig",
+            "redirectUris": [
+                "http://localhost:8080/missing-assertion-sig/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8080/missing-assertion-sig/saml",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8080/missing-assertion-sig/saml",
+                "saml_single_logout_service_url_post": "http://localhost:8080/missing-assertion-sig/saml",
+                "saml_single_logout_service_url_redirect": "http://localhost:8080/missing-assertion-sig/saml",
+                "saml.server.signature": "true",
+                "saml.assertion.signature": "false",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "clientId": "http://localhost:8081/bad-assertion-sales-post-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/bad-assertion-sales-post-sig/",
+            "adminUrl": "http://localhost:8080/bad-assertion-sales-post-sig/saml",
+            "redirectUris": [
+                "http://localhost:8080/bad-assertion-sales-post-sig/*"
+            ],
+            "attributes": {
+                "saml.assertion.signature": "true",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "clientId": "http://localhost:8081/input-portal/",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "protocol": "saml",
+            "baseUrl": "http://localhost:8080/input-portal",
+            "redirectUris": [
+                "http://localhost:8080/input-portal/*"
+            ],
+            "attributes": {
+                "saml.authnstatement": "true",
+                "saml_assertion_consumer_url_post": "http://localhost:8080/input-portal/saml",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8080/input-portal/saml",
+                "saml_single_logout_service_url_post": "http://localhost:8080/input-portal/saml",
+                "saml_single_logout_service_url_redirect": "http://localhost:8080/input-portal/saml"
+            }
+        },
+        {
+            "clientId": "http://localhost:8081/sales-post-assertion-and-response-sig/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/sales-post-assertion-and-response-sig",
+            "redirectUris": [
+                "http://localhost:8080/sales-post-assertion-and-response-sig/*"
+            ],
+            "attributes": {
+                "saml_assertion_consumer_url_post": "http://localhost:8080/sales-post-assertion-and-response-sig/saml",
+                "saml_assertion_consumer_url_redirect": "http://localhost:8080/sales-post-assertion-and-response-sig/saml",
+                "saml_single_logout_service_url_post": "http://localhost:8080/sales-post-assertion-and-response-sig/saml",
+                "saml_single_logout_service_url_redirect": "http://localhost:8080/sales-post-assertion-and-response-sig/saml",
+                "saml.server.signature": "true",
+                "saml.assertion.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
+            "clientId": "http://localhost:8081/sales-post2/",
+            "enabled": true,
+            "fullScopeAllowed": true,
+            "protocol": "saml",
+            "baseUrl": "http://localhost:8080/sales-post2",
+            "redirectUris": [
+                "http://localhost:8080/sales-post2/*"
+            ],
+            "attributes": {
+                "saml.authnstatement": "true",
+                "saml_assertion_consumer_url_post": "http://localhost:8080/sales-post2/saml",
+                "saml_single_logout_service_url_post": "http://localhost:8080/sales-post2/saml",
+                "saml_idp_initiated_sso_url_name": "sales-post2",
+                "saml_idp_initiated_sso_relay_state": "redirectTo=/foo"
+            }
+        },
+        {
             "clientId": "http://localhost:8081/sales-post/",
             "enabled": true,
             "fullScopeAllowed": true,
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml
index 4207f91..aa2c4b7 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/keycloak-saml/web.xml
@@ -28,6 +28,10 @@
         <url-pattern>/*</url-pattern>
     </servlet-mapping>
 
+    <error-page>
+        <location>/error.html</location>
+    </error-page>
+
     <security-constraint>
         <web-resource-collection>
             <web-resource-name>Application</web-resource-name>
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
index 215da8e..8c996d6 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/arquillian.xml
@@ -150,11 +150,11 @@
         </configuration>
     </container>
     
-    <!-- PREVIOUS VERSIONS OF KEYCLOAK FOR MIGRATION TESTS -->
+    <!-- PREVIOUS VERSION OF KEYCLOAK FOR MIGRATION TESTS -->
     
-    <container qualifier="auth-server-jboss-kc16" mode="manual" >
+    <container qualifier="auth-server-jboss-migration" mode="manual" >
         <configuration>
-            <property name="enabled">${auth.server.jboss.kc16}</property>
+            <property name="enabled">${auth.server.jboss.migration}</property>
             <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
             <property name="jbossHome">${keycloak.migration.home}</property>
             <property name="javaVmArguments">
@@ -164,62 +164,10 @@
                 -Dkeycloak.migration.strategy=OVERWRITE_EXISTING
                 -Dkeycloak.migration.realmName=Migration
                 -Djboss.socket.binding.port-offset=${auth.server.port.offset} 
-                -Xms64m -Xmx512m -XX:MaxPermSize=256m
-            </property>
-            <property name="managementPort">${auth.server.management.port}</property>
-            <property name="startupTimeoutInSeconds">${auth.server.startup.timeout}</property>
-        </configuration>
-    </container>
-    
-    <container qualifier="auth-server-jboss-kc15" mode="manual" >
-        <configuration>
-            <property name="enabled">${auth.server.jboss.kc15}</property>
-            <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
-            <property name="jbossHome">${keycloak.migration.home}</property>
-            <property name="javaVmArguments">
-                -Dkeycloak.migration.action=import 
-                -Dkeycloak.migration.provider=singleFile
-                -Dkeycloak.migration.file=${keycloak.migration.file}
-                -Dkeycloak.migration.strategy=OVERWRITE_EXISTING
-                -Dkeycloak.migration.realmName=Migration
-                -Djboss.socket.binding.port-offset=${auth.server.port.offset} 
-                -Xms64m -Xmx512m -XX:MaxPermSize=256m
+                ${auth.server.memory.settings}
             </property>
             <property name="managementPort">${auth.server.management.port}</property>
-            <property name="startupTimeoutInSeconds">${auth.server.startup.timeout}</property>
-        </configuration>
-    </container>
-    
-    <container qualifier="auth-server-jboss-kc14" mode="manual" >
-        <configuration>
-            <property name="enabled">${auth.server.jboss.kc14}</property>
-            <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
-            <property name="jbossHome">${keycloak.migration.home}</property>
-            <property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
-            <property name="managementPort">${auth.server.management.port}</property>
-            <property name="startupTimeoutInSeconds">${auth.server.startup.timeout}</property>
-        </configuration>
-    </container>
-    
-    <container qualifier="auth-server-jboss-kc13" mode="manual" >
-        <configuration>
-            <property name="enabled">${auth.server.jboss.kc13}</property>
-            <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
-            <property name="jbossHome">${keycloak.migration.home}</property>
-            <property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
-            <property name="managementPort">${auth.server.management.port}</property>
-            <property name="startupTimeoutInSeconds">${auth.server.startup.timeout}</property>
-        </configuration>
-    </container>
-    
-    <container qualifier="auth-server-jboss-kc12" mode="manual" >
-        <configuration>
-            <property name="enabled">${auth.server.jboss.kc12}</property>
-            <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
-            <property name="jbossHome">${keycloak.migration.home}</property>
-            <property name="javaVmArguments">-Djboss.socket.binding.port-offset=${auth.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m</property>
-            <property name="managementPort">${auth.server.management.port}</property>
-            <property name="startupTimeoutInSeconds">${auth.server.startup.timeout}</property>
+            <property name="startupTimeoutInSeconds">${auth.server.jboss.startup.timeout}</property>
         </configuration>
     </container>
             
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json
new file mode 100644
index 0000000..19d8c55
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/enforcer-config-paths-same-name.json
@@ -0,0 +1,59 @@
+{
+  "realm": "test-realm-authz",
+  "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+  "auth-server-url": "http://localhost:8180/auth",
+  "ssl-required": "external",
+  "resource": "test-app-authz",
+  "bearer-only": true,
+  "credentials": {
+    "secret": "secret"
+  },
+  "policy-enforcer": {
+    "paths": [
+      {
+        "path": "/v1/product/*",
+        "methods": [
+          {
+            "method": "POST",
+            "scopes": [
+              "create"
+            ]
+          }
+        ]
+      },
+      {
+        "path": "/v1/product/*",
+        "methods": [
+          {
+            "method": "GET",
+            "scopes": [
+              "view"
+            ]
+          }
+        ]
+      },
+      {
+        "path": "/v1/product/*",
+        "methods": [
+          {
+            "method": "PUT",
+            "scopes": [
+              "update"
+            ]
+          }
+        ]
+      },
+      {
+        "path": "/v1/product/*",
+        "methods": [
+          {
+            "method": "DELETE",
+            "scopes": [
+              "delete"
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json
new file mode 100644
index 0000000..b1a6f5a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/test-authz-realm.json
@@ -0,0 +1,50 @@
+{
+  "id": "test-realm-authz",
+  "realm": "test-realm-authz",
+  "enabled": true,
+  "sslRequired": "external",
+  "privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
+  "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+  "requiredCredentials": [ "password" ],
+  "users": [
+    {
+      "username": "service-account-test-app-authz",
+      "enabled": true,
+      "serviceAccountClientId": "test-app-authz",
+      "clientRoles": {
+        "test-app-authz" : ["uma_protection"]
+      }
+    }
+  ],
+  "clients": [
+    {
+      "clientId": "test-app-authz",
+      "enabled": true,
+      "baseUrl": "/test-app-authz",
+      "adminUrl": "/test-app-authz",
+      "bearerOnly": false,
+      "authorizationSettings": {
+        "allowRemoteResourceManagement": true,
+        "policyEnforcementMode": "ENFORCING",
+        "resources": [
+          {
+            "name": "Product Resource",
+            "uri": "/v1/product/*",
+            "scopes": [
+              {
+                "name": "view",
+                "name": "create",
+                "name": "delete",
+                "name": "update"
+              }
+            ]
+          }
+        ]
+      },
+      "redirectUris": [
+        "/test-app-authz/*"
+      ],
+      "secret": "secret"
+    }
+  ]
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem
index 4c589e8..a526c93 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/certificate.pem
@@ -1,13 +1,21 @@
-MIICWwIBAAKBgQCqXOsp76WfwXSNCU5AOix6SDhNR7MOdEtawJRmdUcBuJd/QeFh
-usLVOwm3a7s1134nlVKBEhOYBzKOY6LulvGDT4wHZUxE6cGJW+dEUd/6jrfZz9Ka
-XyATzLUn2BKBQZqRleQPKupwaOGQqQGQ4OmJrWKqG77Rb5O7GLNNDRCGpwIDAQAB
-AoGAA4sJLQcZ57erR9+gq/9Ju4VS/nB2Td+nTYzhyTu5LVT8eZ4SJOkwciTXL+Ri
-sVz497PIUnzgwXGs4H87/UBQZ4UJNz+kTC3L6nr4b5bWoIxoiY76R+gzlYiNEV9s
-QsX+K1FNKKMnEVa7t3DvbCFdlmt+4Agh/KQCU92Q13mj+WECQQDRF+BY1emtFfVC
-2miuSWorMLoaKv5At3BMgcs4KPzlfpMiEOMM/m1jmGrqUm40RZlnkhKEqQB0VeqF
-27gMGZuxAkEA0JTHqZDfcf5bBYhWzE3+Ec9A22/ZQgCiuV+DmWhCYxHLFsOYPkhT
-0jAibfJc8E8VchXMjeDktBAyotylQO1V1wJAcZisLPdCdeOpFMH9/zopcP+PC+px
-qY0/eIFHe+JgyvnCS86q3ANaQLKs21MfRkzNtAQbBXGfqpSGzmR5kDFVcQJAX1YR
-qMSKDS2IZw/5NGrVnUhQybvm3s8xkW9B1GWeKnAglqgSNy2R+nl70ys7Ja/QCpRC
-KftILbFVo7Eca3/PgwJAM5xMmg3Yx/WKkiCREvKXIGKOKN5rGWhHoLnYJHlsOi1r
-Z7Bef90rMp2kDrfLUAgrIJH06kxB+3oPRcmgjWlmDQ==
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAIzE3vQp7EQWMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwMjI5MDgzMDU0WhcNNDMwNzE2MDgzMDU0WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAp1+GzdEkt2FZbISXYO12503FL6Oh8s4+tJ2fE66N8IezhugP8xiySDfW
+TEMaO5Z2TaTnQQoF9SSZ9Edq1GPxpBX0cdkCOBopEGdlb3hUYDeMaDMs18KGemUc
+Fj+CWB5VVcbmWMJ36WCz7FC+Oe38tmujR1AJpJL3pwqazyWIZzPqX8rW+rrNPGKP
+C96oBPZMb4RJWivLBJi/o5MGSpo1sJNtxyF4zUUI00LX0wZAV1HH1XErd1Vz41on
+nmB+tj9nevVRR4rDV280IELp9Ud0PIb3w843uJtwfSAwVG0pT6hv1VBDrBxTS08N
+dPU8CtkQAXzCCr8nqfAbUFOhcWRQgQIDAQABo1AwTjAdBgNVHQ4EFgQUFE+uUZAI
+n57ArEylqhCmHkAenTEwHwYDVR0jBBgwFoAUFE+uUZAIn57ArEylqhCmHkAenTEw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApkgD3OCtw3+sk7GR1YaJ
+xNd8HT+fxXmnLqGnCQWX8lRIg5vj1PDMRev6vlIK3JfQV3zajcpKFfpy96klWsJy
+ZLYBVW2QOtMzDdQ9I8dS4Pn/SJ/Vo/M/ucfY4ttcuUL3oQCrI/c/u9tcamGMfbwd
+658MlXrUvt4B6qXY5AbgUvYR25P86uw7hSFMq5tQftNQsLbOh2FEeIiKhpgI7w8S
+SPajaWjUXsfHc5H7f9MciE2NS1Vd3AViGrVWP1rgQ1Iv0UyQVQrnjmIs12ENJmTd
+5lDqra5FJhaO7+RUG6er8n8HwXzhHkPmezGqtxWKikjitqvDY9prB3omJSa4Led+
+AQ==
+-----END CERTIFICATE-----
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem
index 906ff55..3169a04 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/client-auth-test/publickey.pem
@@ -1 +1,9 @@
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApnZ/E2BUULHjsRiSnEgZ
+4vGe15BRqZPdkHR+NcvVYpThc7JqY6nZrdrwO9sOjlMC5e2Q18Fypi4KbJpGSe9r
+0DPgcbPsHSoe2xFO3M8XBE0DyoRblaQFhe6p/sj3ak32k2zn+fMZUmlx/MTNQh1I
+Cki7So0NDCBXt8XGZNnEyvKeXOUZP5qicP9KxVAQiWJvlkaTjc8rrRTmf+HWw/Qf
+gQC0tzBRpa7T+RpW9O+rnWfOaNfTkTb9itIc+ZOa2Z4iidZ7+ifMOp9cNT641Wb6
+iYqJ2ufqY+msxI54tYM1tPgGS7r4SnCwmnqTaO383wXUl8TQ7qStmAWIepV3nNyu
+AQIDAQAB
+-----END PUBLIC KEY-----
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json
index 99e8614..d8c4dc1 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/META-INF/keycloak-server.json
@@ -90,7 +90,8 @@
             "driverDialect": "${keycloak.connectionsJpa.driverDialect:}",
             "user": "${keycloak.connectionsJpa.user:sa}",
             "password": "${keycloak.connectionsJpa.password:}",
-            "databaseSchema": "${keycloak.connectionsJpa.databaseSchema:update}",
+            "initializeEmpty": true,
+            "migrationStrategy": "update",
             "showSql": "${keycloak.connectionsJpa.showSql:false}",
             "formatSql": "${keycloak.connectionsJpa.formatSql:true}",
             "globalStatsInterval": "${keycloak.connectionsJpa.globalStatsInterval:-1}"
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6SAMLFilterAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6SAMLFilterAdapterTest.java
index 627e5f3..1dcf846 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6SAMLFilterAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6SAMLFilterAdapterTest.java
@@ -8,5 +8,5 @@ import org.keycloak.testsuite.arquillian.annotation.UseServletFilter;
  * @author mhajas
  */
 @AppServerContainer("app-server-eap6")
-public class EAPSAMLFilterAdapterTest extends AbstractSAMLFilterServletAdapterTest {
+public class EAP6SAMLFilterAdapterTest extends AbstractSAMLFilterServletAdapterTest {
 }
diff --git a/testsuite/integration-arquillian/tests/other/adapters/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
index 9c49390..15fc1c4 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
@@ -172,6 +172,18 @@
                             </systemPropertyVariables>
                         </configuration>
                     </plugin>
+                    <plugin>
+                        <groupId>org.jboss.shrinkwrap.resolver</groupId>
+                        <artifactId>shrinkwrap-resolver-maven-plugin</artifactId>
+                        <version>${version.shrinkwrap.resolvers}</version>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>propagate-execution-context</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
                 </plugins>
             </build>
         </profile>
diff --git a/testsuite/integration-arquillian/tests/other/console/pom.xml b/testsuite/integration-arquillian/tests/other/console/pom.xml
index d9232e8..2459c6d 100644
--- a/testsuite/integration-arquillian/tests/other/console/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/console/pom.xml
@@ -36,6 +36,26 @@
     </properties>
 
     <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>properties-maven-plugin</artifactId>
+                <version>1.0.0</version>
+                <executions>
+                    <execution>
+                        <phase>process-resources</phase>
+                        <goals>
+                            <goal>read-project-properties</goal>
+                        </goals>
+                        <configuration>
+                            <files>
+                                <file>${testsuite.constants}</file>
+                            </files>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
         <pluginManagement>
             <plugins>
                 <plugin>
@@ -48,10 +68,11 @@
                                 <goal>copy-resources</goal>
                             </goals>
                             <configuration>
-                                <outputDirectory>${auth.server.home}/themes</outputDirectory>
+                                <outputDirectory>${keycloak.theme.dir}</outputDirectory>
                                 <resources>
                                     <resource>
                                         <directory>src/main/resources/themes</directory>
+                                        <filtering>true</filtering>
                                     </resource>
                                 </resources>
                             </configuration>
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java
index 41e62c9..d19bae7 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/KerberosUserProviderForm.java
@@ -45,6 +45,10 @@ public class KerberosUserProviderForm extends Form {
         setInputValue(consoleDisplayNameInput, name);
     }
 
+    public String getConsoleDisplayNameInput() {
+        return getInputValue(consoleDisplayNameInput);
+    }
+
     public void setPriorityInput(Integer priority) {
         setInputValue(priorityInput, String.valueOf(priority));
     }
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/UserFederation.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/UserFederation.java
index c0dd078..06405ee 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/UserFederation.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/UserFederation.java
@@ -2,13 +2,18 @@ package org.keycloak.testsuite.console.page.federation;
 
 import org.jboss.arquillian.graphene.findby.FindByJQuery;
 import org.keycloak.testsuite.console.page.AdminConsoleRealm;
+import org.keycloak.testsuite.console.page.fragment.DataTable;
+import org.keycloak.testsuite.console.page.fragment.ModalDialog;
+import org.keycloak.testsuite.util.UIUtils;
 import org.openqa.selenium.By;
+import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.ui.Select;
 
 import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
 
 /**
- * Created by fkiss.
+ * @author fkiss
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
  */
 public class UserFederation extends AdminConsoleRealm {
 
@@ -20,9 +25,37 @@ public class UserFederation extends AdminConsoleRealm {
     @FindByJQuery("select[ng-model*='selectedProvider']")
     private Select addProviderSelect;
 
-    public void addProvider(String provider) {
-        waitUntilElement(By.cssSelector("select[ng-model*='selectedProvider']")).is().present();
+    @FindBy(xpath = "//div[./h1/span[text()='User Federation']]/table")
+    private FederationsTable federationsTable;
+
+    public FederationsTable table() {
+        return federationsTable;
+    }
+
+    public void addFederation(String provider) {
         addProviderSelect.selectByVisibleText(provider);
     }
 
+    public boolean hasProvider(String provider) {
+        return UIUtils.selectContainsOption(addProviderSelect, provider);
+    }
+
+    public class FederationsTable extends DataTable {
+        @FindBy(xpath = "//div[@class='modal-dialog']")
+        private ModalDialog modalDialog;
+
+        public void editFederation(String federation) {
+            clickRowActionButton(getRowByLinkText(federation), "Edit");
+        }
+
+        public void removeFederation(String federation) {
+            clickRowActionButton(getRowByLinkText(federation), "Delete");
+            modalDialog.confirmDeletion();
+        }
+
+        public int getFederationsCount() {
+            return rows().size();
+        }
+    }
+
 }
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/messages/messages_cs.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/messages/messages_cs.properties
new file mode 100644
index 0000000..f2fd7e0
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/messages/messages_cs.properties
@@ -0,0 +1,5 @@
+#encoding: utf-8
+doSave=Uložit
+doCancel=Zrušit
+editAccountHtmlTitle=Upravit účet
+locale_cs=Čeština
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/messages/messages_en.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/messages/messages_en.properties
new file mode 100644
index 0000000..cc26e68
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/messages/messages_en.properties
@@ -0,0 +1,2 @@
+#encoding: utf-8
+locale_cs=Čeština
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/theme.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/theme.properties
new file mode 100644
index 0000000..7bdb8fe
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/account/theme.properties
@@ -0,0 +1,2 @@
+parent=${theme-default-name}
+locales=en,cs
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/messages/admin-messages_cs.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/messages/admin-messages_cs.properties
new file mode 100644
index 0000000..9a9ef0e
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/messages/admin-messages_cs.properties
@@ -0,0 +1,7 @@
+#encoding: utf-8
+enabled=Povolit
+save=Uložit
+cancel=Zrušit
+onText=ZAP
+offText=VYP
+realm-settings=Nastavení Realmu
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/messages/messages_cs.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/messages/messages_cs.properties
new file mode 100644
index 0000000..e032076
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/messages/messages_cs.properties
@@ -0,0 +1,2 @@
+#encoding: utf-8
+invalidPasswordMinLengthMessage=Neplatné heslo: musí mít alespoň {0} znaků.
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/theme.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/theme.properties
new file mode 100644
index 0000000..7bdb8fe
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/admin/theme.properties
@@ -0,0 +1,2 @@
+parent=${theme-default-name}
+locales=en,cs
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/email/theme.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/email/theme.properties
new file mode 100644
index 0000000..7bdb8fe
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/email/theme.properties
@@ -0,0 +1,2 @@
+parent=${theme-default-name}
+locales=en,cs
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/messages/messages_cs.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/messages/messages_cs.properties
new file mode 100644
index 0000000..3c43a7b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/messages/messages_cs.properties
@@ -0,0 +1,11 @@
+#encoding: utf-8
+doLogIn=Přihlásit
+doRegister=Registrovat se
+doCancel=Zrušit
+doSubmit=Odeslat
+doForgotPassword=Zapomněli jste heslo?
+locale_cs=Čeština
+username=Uživatelské jméno
+usernameOrEmail=Uživatelské jméno nebo email
+email=Email
+password=Heslo
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/messages/messages_en.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/messages/messages_en.properties
new file mode 100644
index 0000000..cc26e68
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/messages/messages_en.properties
@@ -0,0 +1,2 @@
+#encoding: utf-8
+locale_cs=Čeština
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/theme.properties b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/theme.properties
new file mode 100644
index 0000000..7bdb8fe
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/resources/themes/internat-test/login/theme.properties
@@ -0,0 +1,2 @@
+parent=${theme-default-name}
+locales=en,cs
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/UserFederationTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/UserFederationTest.java
new file mode 100644
index 0000000..d136a0f
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/UserFederationTest.java
@@ -0,0 +1,58 @@
+package org.keycloak.testsuite.console.federation;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.testsuite.console.AbstractConsoleTest;
+import org.keycloak.testsuite.console.page.federation.CreateKerberosUserProvider;
+import org.keycloak.testsuite.console.page.federation.UserFederation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vaclav Muzikar <vmuzikar@redhat.com>
+ */
+public class UserFederationTest extends AbstractConsoleTest {
+    @Page
+    private UserFederation userFederationPage;
+
+    @Page
+    private CreateKerberosUserProvider createKerberosUserProviderPage;
+
+    @Before
+    public void beforeUserFederationTest() {
+        userFederationPage.navigateTo();
+    }
+
+    @Test
+    public void availableProviders() {
+        assertTrue(userFederationPage.hasProvider("ldap"));
+        assertTrue(userFederationPage.hasProvider("kerberos"));
+    }
+
+    @Test
+    public void addRemoveFederation() {
+        final String federationName = "KerberosProvider";
+
+        userFederationPage.addFederation("kerberos");
+        assertTrue(createKerberosUserProviderPage.isCurrent());
+
+        createKerberosUserProviderPage.form().setConsoleDisplayNameInput(federationName);
+        createKerberosUserProviderPage.form().setKerberosRealmInput("KEYCLOAK.ORG");
+        createKerberosUserProviderPage.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");
+        createKerberosUserProviderPage.form().setKeyTabInput("http.keytab");
+        createKerberosUserProviderPage.form().save();
+        assertAlertSuccess();
+        userFederationPage.navigateTo();
+
+        assertEquals(1, userFederationPage.table().getFederationsCount());
+
+        userFederationPage.table().editFederation(federationName);
+        assertEquals(federationName, createKerberosUserProviderPage.form().getConsoleDisplayNameInput());
+        userFederationPage.navigateTo();
+
+        userFederationPage.table().removeFederation(federationName);
+        assertEquals(0, userFederationPage.table().getFederationsCount());
+    }
+}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/InternationalizationTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/InternationalizationTest.java
index 090288b..97cb308 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/InternationalizationTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/realm/InternationalizationTest.java
@@ -4,6 +4,7 @@ import org.jboss.arquillian.graphene.page.Page;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.keycloak.representations.idm.RealmRepresentation;
 import org.keycloak.testsuite.auth.page.AuthRealm;
 import org.keycloak.testsuite.console.page.fragment.Dropdown;
 import org.keycloak.testsuite.console.page.realm.ThemeSettings;
@@ -17,6 +18,13 @@ import static org.keycloak.testsuite.util.URLAssert.*;
  * @author Vaclav Muzikar <vmuzikar@redhat.com>
  */
 public class InternationalizationTest extends AbstractRealmTest {
+    private static final String THEME_NAME = "internat-test";
+    private static final String LOCALE_CS_NAME = "Čeština";
+
+    private static final String LABEL_CS_PASSWORD = "Heslo";
+    private static final String LABEL_CS_REALM_SETTINGS = "Nastavení Realmu";
+    private static final String LABEL_CS_EDIT_ACCOUNT = "Upravit účet";
+
     @Page
     private ThemeSettings themeSettingsPage;
 
@@ -25,6 +33,13 @@ public class InternationalizationTest extends AbstractRealmTest {
 
     @Before
     public void beforeInternationalizationTest() {
+        RealmRepresentation realmRepresentation = testRealmResource().toRepresentation();
+        realmRepresentation.setAccountTheme(THEME_NAME);
+        realmRepresentation.setAdminTheme(THEME_NAME);
+        realmRepresentation.setEmailTheme(THEME_NAME);
+        realmRepresentation.setLoginTheme(THEME_NAME);
+        testRealmResource().update(realmRepresentation);
+
         realmSettingsPage.navigateTo();
         tabs().themes();
         themeSettingsPage.setInternatEnabled(true);
@@ -47,14 +62,14 @@ public class InternationalizationTest extends AbstractRealmTest {
     public void loginInternationalization() {
         testRealmAdminConsolePage.navigateTo();
 
-        localeDropdown.selectByText("Español");
-        assertLocale(".//label[@for='password']", "Contraseña"); // Password
+        localeDropdown.selectByText(LOCALE_CS_NAME);
+        assertLocale(".//label[@for='password']", LABEL_CS_PASSWORD);
 
         loginToTestRealmConsoleAs(testUser);
-        assertConsoleLocale("Temas");
+        assertConsoleLocale(LABEL_CS_REALM_SETTINGS);
 
         testRealmAccountPage.navigateTo();
-        assertAccountLocale("Cuenta");
+        assertAccountLocale(LABEL_CS_EDIT_ACCOUNT);
     }
 
     /**
@@ -65,24 +80,24 @@ public class InternationalizationTest extends AbstractRealmTest {
         testRealmAccountPage.navigateTo();
         loginPage.form().login(testUser);
 
-        localeDropdown.selectByText("Français");
+        localeDropdown.selectByText(LOCALE_CS_NAME);
         testRealmAccountPage.navigateTo();
-        assertAccountLocale("Compte");
+        assertAccountLocale(LABEL_CS_EDIT_ACCOUNT);
 
         deleteAllCookiesForTestRealm();
 
         loginToTestRealmConsoleAs(testUser);
-        assertConsoleLocale("Thèmes");
+        assertConsoleLocale(LABEL_CS_REALM_SETTINGS);
     }
 
     private void assertConsoleLocale(String expected) {
         assertCurrentUrlEquals(realmSettingsPage);
-        assertLocale(".//a[contains(@href,'/theme-settings')]", expected); // Themes
+        assertLocale(".//div[@class='nav-category'][1]/ul/li[1]//a", expected); // Realm Settings
     }
 
     private void assertAccountLocale(String expected) {
         assertCurrentUrlEquals(testRealmAccountPage);
-        assertLocale(".//div[contains(@class,'bs-sidebar')]/ul/li", expected); // Account
+        assertLocale(".//div[contains(@class,'content-area')]/div[@class='row']/div/h2", expected); // Edit Account
     }
 
     private void assertLocale(String xpathSelector, String expected) {
diff --git a/testsuite/integration-arquillian/tests/other/pom.xml b/testsuite/integration-arquillian/tests/other/pom.xml
index bb238bf..6b0f83c 100644
--- a/testsuite/integration-arquillian/tests/other/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/pom.xml
@@ -59,7 +59,7 @@
                                         <artifactId>integration-arquillian-tests-base</artifactId>
                                         <version>${project.version}</version>
                                         <type>test-jar</type>
-                                        <includes>arquillian.xml,keycloak-add-user.json,kerberos/*</includes>
+                                        <includes>arquillian.xml,keycloak-add-user.json,test-constants.properties,kerberos/*</includes>
                                     </artifactItem>
                                 </artifactItems>
                             </configuration>
diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml
index 6c25059..3e97fc1 100755
--- a/testsuite/integration-arquillian/tests/pom.xml
+++ b/testsuite/integration-arquillian/tests/pom.xml
@@ -37,7 +37,7 @@
         <module>base</module>
         <module>other</module>
     </modules>
-    
+
     <properties>
         <auth.server>undertow</auth.server>
         <auth.server.undertow>true</auth.server.undertow>
@@ -54,7 +54,6 @@
         <auth.server.management.port>10090</auth.server.management.port>
         <auth.server.management.port.jmx>10099</auth.server.management.port.jmx>
         <auth.server.ssl.required>false</auth.server.ssl.required>
-        <auth.server.jboss.startup.timeout>60</auth.server.jboss.startup.timeout>
         <auth.server.memory.settings>-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m</auth.server.memory.settings>
         <auth.server.config.property.name>serverConfig</auth.server.config.property.name>
         <auth.server.adapter.impl.class>org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</auth.server.adapter.impl.class>
@@ -74,8 +73,9 @@
         <frontend.console.output>true</frontend.console.output>
         <backends.console.output>true</backends.console.output>
 
-        <testsuite.constants>test-constants.properties</testsuite.constants>
+        <testsuite.constants>${project.build.directory}/dependency/test-constants.properties</testsuite.constants>
 
+        <skip.add.user.json>false</skip.add.user.json>
     </properties>
 
     <build>
@@ -116,6 +116,7 @@
                                 <goal>copy-resources</goal>
                             </goals>
                             <configuration>
+                                <skip>${skip.add.user.json}</skip>
                                 <outputDirectory>${auth.server.config.dir}</outputDirectory>
                                 <resources>
                                     <resource>
@@ -178,7 +179,7 @@
                         <properties>
                             <property>
                                 <name>listener</name>
-                                <value>org.keycloak.testsuite.util.TestEventsLogger</value>
+                                <value>org.keycloak.testsuite.util.TestEventsLogger,org.keycloak.testsuite.util.junit.AggregateResultsReporter</value>
                             </property>
                         </properties>
                     </configuration>
@@ -402,7 +403,7 @@
             </build>
         </profile>
 
-        <!-- Profiles for migration tests-->
+        <!-- Profile for migration tests-->
         
         <profile>
             <id>migration</id>
@@ -411,31 +412,9 @@
                     <name>migrated.auth.server.version</name>
                 </property>
             </activation>
-            <properties>
-                <!--diable exclusion pattern for migration tests, which is enabled by default in the base/pom.xml-->
-                <exclude.migration>-</exclude.migration>
-            </properties>
             <build>
                 <plugins>
                     <plugin>
-                        <artifactId>maven-enforcer-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>enforce-properties</id>
-                                <goals>
-                                    <goal>enforce</goal>
-                                </goals>
-                                <configuration>
-                                    <rules>
-                                        <requireProperty>
-                                            <property>migrated.auth.server.version</property>
-                                        </requireProperty>
-                                    </rules>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
                         <artifactId>maven-dependency-plugin</artifactId>
                         <executions>
                             <execution>
@@ -448,7 +427,7 @@
                                     <artifactItems>
                                         <artifactItem>
                                             <groupId>org.keycloak.testsuite</groupId>
-                                            <artifactId>${migrated.auth.server.jboss.artifactId}</artifactId>
+                                            <artifactId>integration-arquillian-migration-server</artifactId>
                                             <version>${project.version}</version>
                                             <type>zip</type>
                                         </artifactItem>
@@ -464,158 +443,16 @@
                         <configuration>
                             <systemPropertyVariables>
                                 <migrated.auth.server.version>${migrated.auth.server.version}</migrated.auth.server.version>
+                                <auth.server.jboss.migration>true</auth.server.jboss.migration>
+                                <keycloak.migration.home>${containers.home}/keycloak-${migrated.auth.server.version}</keycloak.migration.home>
+                                <keycloak.migration.file>src/test/resources/migration-test/migration-realm-${migrated.auth.server.version}.json</keycloak.migration.file>
                             </systemPropertyVariables>
                         </configuration>
                     </plugin>
                 </plugins>
             </build>
         </profile>        
-        
-        <profile>
-            <id>migration-kc16</id>
-            <activation>
-                <property>
-                    <name>migrated.auth.server.version</name>
-                    <value>1.6.1.Final</value>
-                </property>
-            </activation>
-            <properties>
-                <migrated.auth.server.jboss.artifactId>integration-arquillian-server-wildfly-kc16</migrated.auth.server.jboss.artifactId>
-            </properties>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <artifactId>maven-surefire-plugin</artifactId>
-                            <configuration>
-                                <systemPropertyVariables>
-                                    <auth.server.jboss.kc16>true</auth.server.jboss.kc16>
-                                    <keycloak.migration.home>${containers.home}/keycloak-${migrated.auth.server.version}</keycloak.migration.home>
-                                    <keycloak.migration.file>src/test/resources/migration-test/migration-realm-16.json</keycloak.migration.file>
-                                </systemPropertyVariables>
-                            </configuration>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        
-        <profile>
-            <id>migration-kc15</id>
-            <activation>
-                <property>
-                    <name>migrated.auth.server.version</name>
-                    <value>1.5.1.Final</value>
-                </property>
-            </activation>
-            <properties>
-                <migrated.auth.server.jboss.artifactId>integration-arquillian-server-wildfly-kc15</migrated.auth.server.jboss.artifactId>
-            </properties>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <artifactId>maven-surefire-plugin</artifactId>
-                            <configuration>
-                                <systemPropertyVariables>
-                                    <auth.server.jboss.kc15>true</auth.server.jboss.kc15>
-                                    <keycloak.migration.home>${containers.home}/keycloak-${migrated.auth.server.version}</keycloak.migration.home>
-                                    <keycloak.migration.file>src/test/resources/migration-test/migration-realm-15.json</keycloak.migration.file>
-                                </systemPropertyVariables>
-                            </configuration>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        
-        <profile>
-            <id>migration-kc14</id>
-            <activation>
-                <property>
-                    <name>migrated.auth.server.version</name>
-                    <value>1.4.0.Final</value>
-                </property>
-            </activation>
-            <properties>
-                <migrated.auth.server.jboss.artifactId>integration-arquillian-server-wildfly-kc14</migrated.auth.server.jboss.artifactId>
-            </properties>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <artifactId>maven-surefire-plugin</artifactId>
-                            <configuration>
-                                <systemPropertyVariables>
-                                    <auth.server.jboss.kc14>true</auth.server.jboss.kc14>
-                                    <keycloak.migration.home>${containers.home}/keycloak-${migrated.auth.server.version}</keycloak.migration.home>
-                                </systemPropertyVariables>
-                            </configuration>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        
-        <profile>
-            <id>migration-kc13</id>
-            <activation>
-                <property>
-                    <name>migrated.auth.server.version</name>
-                    <value>1.3.1.Final</value>
-                </property>
-            </activation>
-            <properties>
-                <migrated.auth.server.jboss.artifactId>integration-arquillian-server-wildfly-kc13</migrated.auth.server.jboss.artifactId>
-            </properties>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <artifactId>maven-surefire-plugin</artifactId>
-                            <configuration>
-                                <systemPropertyVariables>
-                                    <auth.server.jboss.kc13>true</auth.server.jboss.kc13>
-                                    <keycloak.migration.home>${containers.home}/keycloak-${migrated.auth.server.version}</keycloak.migration.home>
-                                </systemPropertyVariables>
-                            </configuration>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-        
-        <profile>
-            <id>migration-kc12</id>
-            <activation>
-                <property>
-                    <name>migrated.auth.server.version</name>
-                    <value>1.2.0.Final</value>
-                </property>
-            </activation>
-            <properties>
-                <migrated.auth.server.jboss.artifactId>integration-arquillian-server-wildfly-kc12</migrated.auth.server.jboss.artifactId>
-            </properties>
-            <build>
-                <pluginManagement>
-                    <plugins>
-                        <plugin>
-                            <artifactId>maven-surefire-plugin</artifactId>
-                            <configuration>
-                                <systemPropertyVariables>
-                                    <auth.server.jboss.kc12>true</auth.server.jboss.kc12>
-                                    <keycloak.migration.home>${containers.home}/keycloak-${migrated.auth.server.version}</keycloak.migration.home>
-                                </systemPropertyVariables>
-                            </configuration>
-                        </plugin>
-                    </plugins>
-                </pluginManagement>
-            </build>
-        </profile>
-
-
-
-
+      
         <profile>
             <id>no-account</id>
             <properties>
@@ -645,6 +482,13 @@
                 </file>
             </activation>
             <dependencies>
+
+                <dependency>
+                    <groupId>org.keycloak.testsuite</groupId>
+                    <artifactId>integration-arquillian-test-utils</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+
                 <!-- TEST DEPENDENCIES -->
                 <dependency>
                     <groupId>junit</groupId>
@@ -780,6 +624,14 @@
                     <groupId>org.keycloak</groupId>
                     <artifactId>keycloak-adapter-spi</artifactId>
                 </dependency>
+                <dependency>
+                    <groupId>org.keycloak</groupId>
+                    <artifactId>keycloak-saml-adapter-api-public</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.keycloak</groupId>
+                    <artifactId>keycloak-authz-client</artifactId>
+                </dependency>
 
                 <!--UNDERTOW-->
 
diff --git a/testsuite/integration-arquillian/test-utils/pom.xml b/testsuite/integration-arquillian/test-utils/pom.xml
new file mode 100644
index 0000000..c03c56b
--- /dev/null
+++ b/testsuite/integration-arquillian/test-utils/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>integration-arquillian</artifactId>
+        <groupId>org.keycloak.testsuite</groupId>
+        <version>2.2.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>integration-arquillian-test-utils</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Test utils</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-configuration</groupId>
+            <artifactId>commons-configuration</artifactId>
+            <version>1.10</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java b/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java
new file mode 100644
index 0000000..a0809c1
--- /dev/null
+++ b/testsuite/integration-arquillian/test-utils/src/main/java/org/keycloak/testsuite/util/junit/AggregateResultsReporter.java
@@ -0,0 +1,269 @@
+package org.keycloak.testsuite.util.junit;
+
+import org.apache.commons.configuration.PropertiesConfiguration;
+
+import org.jboss.logging.Logger;
+
+import org.junit.Ignore;
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Aggregates jUnit test results into a single report - XML file.
+ */
+public class AggregateResultsReporter extends RunListener {
+
+    private static final Logger LOGGER = Logger.getLogger(AggregateResultsReporter.class);
+
+    private final Document xml;
+    private final File reportFile;
+    private final boolean working;
+
+    private final AtomicInteger tests = new AtomicInteger(0);
+    private final AtomicInteger errors = new AtomicInteger(0);
+    private final AtomicInteger failures = new AtomicInteger(0);
+    private final AtomicInteger ignored = new AtomicInteger(0);
+    private final AtomicLong suiteStartTime = new AtomicLong(0L);
+
+    private final AtomicReference<Element> testsuite = new AtomicReference<Element>();
+
+    private final Map<String, Long> testTimes = new HashMap<String, Long>();
+
+    public AggregateResultsReporter() {
+        boolean working = true;
+        Document xml = null;
+        try {
+            xml = createEmptyDocument();
+        } catch (ParserConfigurationException ex) {
+            LOGGER.error("Failed to create XML DOM - reporting will not be done", ex);
+            working = false;
+        }
+
+        File reportFile = null;
+        try {
+            reportFile = createReportFile();
+        } catch (Exception ex) {
+            LOGGER.error("Failed to create log file - reporting will not be done", ex);
+            working = false;
+        }
+
+        this.working = working;
+        this.xml = xml;
+        this.reportFile = reportFile;
+    }
+
+    private Document createEmptyDocument() throws ParserConfigurationException {
+        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+        return builder.newDocument();
+    }
+
+    private File createReportFile() throws Exception {
+        PropertiesConfiguration config = new PropertiesConfiguration(System.getProperty("testsuite.constants"));
+        config.setThrowExceptionOnMissing(true);
+
+        final File logDir = new File(config.getString("log-dir"));
+        logDir.mkdirs();
+
+        final File reportFile = new File(logDir, "junit-report.xml").getAbsoluteFile();
+        reportFile.createNewFile();
+
+        return reportFile;
+    }
+
+    @Override
+    public void testRunStarted(Description description) throws Exception {
+        if (working) {
+            suiteStartTime.set(System.currentTimeMillis());
+
+            Element testsuite = xml.createElement("testsuite");
+
+            if (description.getChildren().size() == 1) {
+                testsuite.setAttribute("name", safeString(description.getChildren().get(0).getDisplayName()));
+            }
+
+            xml.appendChild(testsuite);
+            this.testsuite.set(testsuite);
+            writeXml();
+        }
+    }
+
+    @Override
+    public void testStarted(Description description) throws Exception {
+        if (working) {
+            testTimes.put(description.getDisplayName(), System.currentTimeMillis());
+        }
+    }
+
+    @Override
+    public void testFinished(Description description) throws Exception {
+        if (working) {
+            if (testTimes.containsKey(description.getDisplayName())) {
+                testsuite.get().appendChild(createTestCase(description));
+                writeXml();
+            }
+        }
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+        if (working) {
+            ignored.incrementAndGet();
+
+            Element testcase = createTestCase(failure.getDescription());
+            Element skipped = xml.createElement("skipped");
+            skipped.setAttribute("message", safeString(failure.getMessage()));
+
+            testcase.appendChild(skipped);
+
+            testsuite.get().appendChild(testcase);
+            writeXml();
+        }
+    }
+
+    @Override
+    public void testFailure(Failure failure) throws Exception {
+        if (working) {
+            if (failure.getDescription().getMethodName() == null) {
+                // before class failed
+                for (Description child : failure.getDescription().getChildren()) {
+                    // mark all methods failed
+                    testFailure(new Failure(child, failure.getException()));
+                }
+            } else {
+                // normal failure
+                Element testcase = createTestCase(failure.getDescription());
+
+                Element element;
+                if (failure.getException() instanceof AssertionError) {
+                    failures.incrementAndGet();
+                    element = xml.createElement("failure");
+                } else {
+                    errors.incrementAndGet();
+                    element = xml.createElement("error");
+                }
+
+                testcase.appendChild(element);
+
+                element.setAttribute("type", safeString(failure.getException().getClass().getName()));
+                element.setAttribute("message", safeString(failure.getMessage()));
+                element.appendChild(xml.createCDATASection(safeString(failure.getTrace())));
+
+                testsuite.get().appendChild(testcase);
+                writeXml();
+            }
+        }
+    }
+
+    @Override
+    public void testIgnored(Description description) throws Exception {
+        if (working) {
+            ignored.incrementAndGet();
+
+            Element testcase = createTestCase(description);
+
+            Element skipped = xml.createElement("skipped");
+            skipped.setAttribute("message", safeString(description.getAnnotation(Ignore.class).value()));
+
+            testcase.appendChild(skipped);
+
+            testsuite.get().appendChild(testcase);
+            writeXml();
+        }
+    }
+
+    @Override
+    public void testRunFinished(Result result) throws Exception {
+        if (working) {
+            writeXml();
+        }
+    }
+
+    private void writeXml() {
+        Element testsuite = this.testsuite.get();
+
+        testsuite.setAttribute("tests", Integer.toString(tests.get()));
+        testsuite.setAttribute("errors", Integer.toString(errors.get()));
+        testsuite.setAttribute("skipped", Integer.toString(ignored.get()));
+        testsuite.setAttribute("failures", Integer.toString(failures.get()));
+        testsuite.setAttribute("time", computeTestTime(suiteStartTime.get()));
+
+        try {
+            Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(reportFile, false), Charset.forName("UTF-8")));
+            try {
+                Transformer t = TransformerFactory.newInstance().newTransformer();
+                t.setOutputProperty(OutputKeys.INDENT, "yes");
+                t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
+                t.transform(new DOMSource(xml), new StreamResult(writer));
+            } catch (TransformerConfigurationException ex) {
+                LOGGER.error("Misconfigured transformer", ex);
+            } catch (TransformerException ex) {
+                LOGGER.error("Unable to save XML file", ex);
+            } finally {
+                writer.close();
+            }
+        } catch (IOException ex) {
+            LOGGER.warn("Unable to open report file", ex);
+        }
+    }
+
+    private String computeTestTime(Long startTime) {
+        if (startTime == null) {
+            return "0";
+        } else {
+            long amount = System.currentTimeMillis() - startTime;
+            return String.format("%.3f", amount / 1000F);
+        }
+    }
+
+    private Element createTestCase(Description description) {
+        tests.incrementAndGet();
+
+        Element testcase = xml.createElement("testcase");
+
+        testcase.setAttribute("name", safeString(description.getMethodName()));
+        testcase.setAttribute("classname", safeString(description.getClassName()));
+        testcase.setAttribute("time", computeTestTime(testTimes.remove(description.getDisplayName())));
+
+        return testcase;
+    }
+
+    private String safeString(String input) {
+        if (input == null) {
+            return "null";
+        }
+
+        return input
+                // first remove color coding (all of it)
+                .replaceAll("\u001b\\[\\d+m", "")
+                // then remove control characters that are not whitespaces
+                .replaceAll("[\\p{Cntrl}&&[^\\p{Space}]]", "");
+    }
+}
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_en.properties b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
index 5c7ff81..8ed1de6 100755
--- a/themes/src/main/resources/theme/base/account/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/account/messages/messages_en.properties
@@ -157,5 +157,7 @@ locale_en=English
 locale_es=Espa\u00F1ol
 locale_fr=Fran\u00e7ais
 locale_it=Italian
+locale_ja=\u65E5\u672C\u8A9E
+locale_no=Norsk
 locale_pt-BR=Portugu\u00EAs (Brasil)
-locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
\ No newline at end of file
+locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_ja.properties b/themes/src/main/resources/theme/base/account/messages/messages_ja.properties
new file mode 100644
index 0000000..82c9cb5
--- /dev/null
+++ b/themes/src/main/resources/theme/base/account/messages/messages_ja.properties
@@ -0,0 +1,153 @@
+# encoding: utf-8
+doSave=保存
+doCancel=キャンセル
+doLogOutAllSessions=全セッションからログアウト
+doRemove=削除
+doAdd=追加
+doSignOut=サインアウト
+
+editAccountHtmlTitle=アカウントの編集
+federatedIdentitiesHtmlTitle=Federated Identities
+accountLogHtmlTitle=アカウントログ
+changePasswordHtmlTitle=パスワード変更
+sessionsHtmlTitle=セッション
+accountManagementTitle=Keycloak アカウント管理
+authenticatorTitle=Authenticator
+applicationsHtmlTitle=アプリケーション
+
+authenticatorCode=ワンタイムコード
+email=Eメール
+firstName=名
+givenName=名
+fullName=氏名
+lastName=姓
+familyName=姓
+password=パスワード
+passwordConfirm=新しいパスワード (確認)
+passwordNew=新しいパスワード
+username=ユーザー名
+address=住所
+street=番地
+locality=市区町村
+region=都道府県
+postal_code=郵便番号
+country=国
+emailVerified=確認済みEメール
+gssDelegationCredential=GSS 代行クレデンシャル
+
+role_admin=管理者
+role_realm-admin=レルムの管理
+role_create-realm=レルムの作成
+role_view-realm=レルムの参照
+role_view-users=ユーザーの参照
+role_view-applications=アプリケーションの参照
+role_view-clients=クライアントの参照
+role_view-events=イベントの参照
+role_view-identity-providers=アイデンティティ プロバイダーの参照
+role_manage-realm=レルムの管理
+role_manage-users=ユーザーの管理
+role_manage-applications=アプリケーションの管理
+role_manage-identity-providers=アイデンティティ プロバイダーの管理
+role_manage-clients=クライアントの管理
+role_manage-events=イベントの管理
+role_view-profile=プロフィールの参照
+role_manage-account=アカウントの管理
+role_read-token=トークンの参照
+role_offline-access=オフラインアクセス
+role_uma_authorization=アクセス権の取得
+client_account=アカウント
+client_security-admin-console=セキュリティ管理コンソール
+client_admin-cli=管理 CLI
+client_realm-management=レルム管理
+client_broker=ブローカー
+
+
+requiredFields=必須
+allFieldsRequired=全ての入力項目が必須
+
+backToApplication=&laquo; アプリケーションに戻る
+backTo={0} に戻る
+
+date=日付
+event=イベント
+ip=IP
+client=クライアント
+clients=クライアント
+details=詳細
+started=開始
+lastAccess=最終アクセス
+expires=有効期限
+applications=アプリケーション
+
+account=アカウント
+federatedIdentity=Federated Identity
+authenticator=Authenticator
+sessions=セッション
+log=ログ
+
+application=アプリケーション
+availablePermissions=使用可能なアクセス権
+grantedPermissions=許可されたアクセス権
+grantedPersonalInfo=許可された個人情報
+additionalGrants=追加の許可
+action=アクション
+inResource=in
+fullAccess=フルアクセス
+offlineToken=オフライントークン
+revoke=許可の取り消し
+
+configureAuthenticators=設定済みの Authenticator
+mobile=モバイル
+totpStep1=<a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> または Google Authenticator (Google認証システム) をご自身のデバイスにインストールしてください。これらのアプリケーションは <a href="https://play.google.com">Google Play</a> と Apple App Store で入手できます。
+totpStep2=アプリケーションを開きバーコードをスキャンするかキーを入力してください。
+totpStep3=アプリケーションで提供されたワンタイムコードを入力して保存をクリックし、セットアップを完了してください。
+
+missingUsernameMessage=ユーザー名を入力してください。
+missingFirstNameMessage=名を入力してください。
+invalidEmailMessage=無効なメールアドレスです。
+missingLastNameMessage=姓を入力してください。
+missingEmailMessage=Eメールを入力してください。
+missingPasswordMessage=パスワードを入力してください。
+notMatchPasswordMessage=パスワードが一致していません。
+
+missingTotpMessage=Authenticator コードを入力してください。
+invalidPasswordExistingMessage=無効な既存のパスワードです。
+invalidPasswordConfirmMessage=新しいパスワード (確認) と一致していません。
+invalidTotpMessage=無効な Authenticator コードです。
+
+usernameExistsMessage=既に存在するユーザー名です。
+emailExistsMessage=既に存在するEメールです。
+
+readOnlyUserMessage=リードオンリーのためアカウントを更新することはできません。
+readOnlyPasswordMessage=リードオンリーのためパスワードを更新することはできません。
+
+successTotpMessage=モバイル Authenticator が設定されました。
+successTotpRemovedMessage=モバイル Authenticator が削除されました。
+
+successGrantRevokedMessage=許可が正常に取り消しされました。
+
+accountUpdatedMessage=アカウントが更新されました。
+accountPasswordUpdatedMessage=パスワードが更新されました。
+
+missingIdentityProviderMessage=アイデンティティ プロバイダーが指定されていません。
+invalidFederatedIdentityActionMessage=無効または存在しないアクションです。
+identityProviderNotFoundMessage=指定されたアイデンティティ プロバイダーが見つかりません。
+federatedIdentityLinkNotActiveMessage=このアイデンティティは有効ではありません。
+federatedIdentityRemovingLastProviderMessage=パスワードがないため最後の Federated Identity を削除できません。
+identityProviderRedirectErrorMessage=アイデンティティ プロバイダーへのリダイレクトに失敗しました。
+identityProviderRemovedMessage=アイデンティティ プロバイダーが正常に削除されました。
+identityProviderAlreadyLinkedMessage={0}から返された Federated Identity は既に他のユーザーに関連付けされています。
+staleCodeAccountMessage=有効期限切れです。再度お試しください。
+consentDenied=同意が拒否されました。
+
+accountDisabledMessage=アカウントが無効です。管理者に連絡してください。
+
+accountTemporarilyDisabledMessage=アカウントが一時的に無効です。管理者に連絡、またはしばらく時間をおいてから再度お試しください。
+invalidPasswordMinLengthMessage=無効なパスワード: 最小 {0} の長さが必要です。
+invalidPasswordMinLowerCaseCharsMessage=無効なパスワード: 少なくとも {0} 文字の小文字を含む必要があります。
+invalidPasswordMinDigitsMessage=無効なパスワード: 少なくとも {0} 文字の数字を含む必要があります。
+invalidPasswordMinUpperCaseCharsMessage=無効なパスワード: 少なくとも {0} 文字の大文字を含む必要があります。
+invalidPasswordMinSpecialCharsMessage=無効なパスワード:  少なくとも {0} 文字の特殊文字を含む必要があります。
+invalidPasswordNotUsernameMessage=無効なパスワード: ユーザー名と同じパスワードは禁止されています。
+invalidPasswordRegexPatternMessage=無効なパスワード: 正規表現パターンと一致しません。
+invalidPasswordHistoryMessage=無効なパスワード: 最近の {0} パスワードのいずれかと同じパスワードは禁止されています。
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/account/messages/messages_no.properties b/themes/src/main/resources/theme/base/account/messages/messages_no.properties
new file mode 100644
index 0000000..3cae31e
--- /dev/null
+++ b/themes/src/main/resources/theme/base/account/messages/messages_no.properties
@@ -0,0 +1,163 @@
+doSave=Lagre
+doCancel=Avbryt
+doLogOutAllSessions=Logg ut av alle sesjoner
+doRemove=Fjern
+doAdd=Legg til
+doSignOut=Logg ut
+
+editAccountHtmlTitle=Rediger konto
+federatedIdentitiesHtmlTitle=Federerte identiteter
+accountLogHtmlTitle=Kontologg
+changePasswordHtmlTitle=Endre passord
+sessionsHtmlTitle=Sesjoner
+accountManagementTitle=Keycloak kontoadministrasjon
+authenticatorTitle=Autentikator
+applicationsHtmlTitle=Applikasjoner
+
+authenticatorCode=Engangskode
+email=E-post
+firstName=Fornavn
+givenName=Fornavn
+fullName=Fullt navn
+lastName=Etternavn
+familyName=Etternavn
+password=Passord
+passwordConfirm=Bekreftelse
+passwordNew=Nytt passord
+username=Brukernavn
+address=Adresse
+street=Gate-/veinavn + husnummer
+locality=By
+region=Fylke
+postal_code=Postnummer
+country=Land
+emailVerified=E-post bekreftet
+gssDelegationCredential=GSS legitimasjonsdelegering
+
+role_admin=Administrator
+role_realm-admin=Administrator for sikkerhetsdomene
+role_create-realm=Opprette sikkerhetsdomene
+role_view-realm=Se sikkerhetsdomene
+role_view-users=Se brukere
+role_view-applications=Se applikasjoner
+role_view-clients=Se klienter
+role_view-events=Se hendelser
+role_view-identity-providers=Se identitetsleverand\u00F8rer
+role_manage-realm=Administrere sikkerhetsdomene
+role_manage-users=Administrere brukere
+role_manage-applications=Administrere applikasjoner
+role_manage-identity-providers=Administrere identitetsleverand\u00F8rer
+role_manage-clients=Administrere klienter
+role_manage-events=Administrere hendelser
+role_view-profile=Se profil
+role_manage-account=Administrere konto
+role_read-token=Lese token
+role_offline-access=Frakoblet tilgang
+role_uma_authorization=Skaffe tillatelser
+client_account=Konto
+client_security-admin-console=Sikkerhetsadministrasjonskonsoll
+client_admin-cli=Kommandolinje-grensesnitt for administrator
+client_realm-management=Sikkerhetsdomene-administrasjon
+client_broker=Broker
+
+
+requiredFields=Obligatoriske felt
+allFieldsRequired=Alle felt m\u00E5 fylles ut
+
+backToApplication=&laquo; Tilbake til applikasjonen
+backTo=Tilbake til {0}
+
+date=Dato
+event=Hendelse
+ip=IP
+client=Klient
+clients=Klienter
+details=Detaljer
+started=Startet
+lastAccess=Sist benyttet
+expires=Utl\u00F8per
+applications=Applikasjoner
+
+account=Konto
+federatedIdentity=Federert identitet
+authenticator=Autentikator
+sessions=Sesjoner
+log=Logg
+
+application=Applikasjon
+availablePermissions=Tilgjengelige rettigheter
+grantedPermissions=Innvilgede rettigheter
+grantedPersonalInfo=Innvilget personlig informasjon
+additionalGrants=Ekstra rettigheter
+action=Handling
+inResource=i
+fullAccess=Full tilgang
+offlineToken=Offline token
+revoke=Opphev rettighet
+
+configureAuthenticators=Konfigurerte autentikatorer
+mobile=Mobiltelefon
+totpStep1=Installer <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> eller Google Authenticator p\u00E5 din enhet. Begge applikasjoner er tilgjengelige p\u00E5 <a href="https://play.google.com">Google Play</a> og Apple App Store.
+totpStep2=\u00C5pne applikasjonen og skann strekkoden eller skriv inn koden.
+totpStep3=Skriv inn engangskoden gitt av applikasjonen og klikk Lagre for \u00E5 fullf\u00F8re.
+
+missingUsernameMessage=Vennligst oppgi brukernavn.
+missingFirstNameMessage=Vennligst oppgi fornavn.
+invalidEmailMessage=Ugyldig e-postadresse.
+missingLastNameMessage=Vennligst oppgi etternavn.
+missingEmailMessage=Vennligst oppgi e-postadresse.
+missingPasswordMessage=Vennligst oppgi passord.
+notMatchPasswordMessage=Passordene er ikke like.
+
+missingTotpMessage=Vennligst oppgi engangskode.
+invalidPasswordExistingMessage=Ugyldig eksisterende passord.
+invalidPasswordConfirmMessage=Passordene er ikke like.
+invalidTotpMessage=Ugyldig engangskode.
+
+usernameExistsMessage=Brukernavnet finnes allerede.
+emailExistsMessage=E-postadressen finnes allerede.
+
+readOnlyUserMessage=Du kan ikke oppdatere kontoen din ettersom den er skrivebeskyttet.
+readOnlyPasswordMessage=Du kan ikke oppdatere passordet ditt ettersom kontoen din er skrivebeskyttet.
+
+successTotpMessage=Autentikator for mobiltelefon er konfigurert.
+successTotpRemovedMessage=Autentikator for mobiltelefon er fjernet.
+
+successGrantRevokedMessage=Vellykket oppheving av rettighet.
+
+accountUpdatedMessage=Kontoen din har blitt oppdatert.
+accountPasswordUpdatedMessage=Ditt passord har blitt oppdatert.
+
+missingIdentityProviderMessage=Identitetsleverand\u00F8r er ikke spesifisert.
+invalidFederatedIdentityActionMessage=Ugyldig eller manglende handling.
+identityProviderNotFoundMessage=Spesifisert identitetsleverand\u00F8r ikke funnet.
+federatedIdentityLinkNotActiveMessage=Denne identiteten er ikke lenger aktiv.
+federatedIdentityRemovingLastProviderMessage=Du kan ikke fjerne siste federerte identitet ettersom du ikke har et passord.
+identityProviderRedirectErrorMessage=Redirect til identitetsleverand\u00F8r feilet.
+identityProviderRemovedMessage=Fjerning av identitetsleverand\u00F8r var vellykket.
+identityProviderAlreadyLinkedMessage=Federert identitet returnert av {0} er allerede koblet til en annen bruker.
+staleCodeAccountMessage=Siden har utl\u00F8pt. Vennligst pr\u00F8v en gang til.
+consentDenied=Samtykke avsl\u00E5tt.
+
+accountDisabledMessage=Konto er deaktivert, kontakt administrator.
+
+accountTemporarilyDisabledMessage=Konto er midlertidig deaktivert, kontakt administrator eller pr\u00F8v igjen senere.
+invalidPasswordMinLengthMessage=Ugyldig passord: minimum lengde {0}.
+invalidPasswordMinLowerCaseCharsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} sm\u00E5 bokstaver.
+invalidPasswordMinDigitsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} sifre.
+invalidPasswordMinUpperCaseCharsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} store bokstaver.
+invalidPasswordMinSpecialCharsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} spesialtegn.
+invalidPasswordNotUsernameMessage=Ugyldig passord: kan ikke v\u00E6re likt brukernavn.
+invalidPasswordRegexPatternMessage=Ugyldig passord: tilfredsstiller ikke kravene for passord-m\u00F8nster.
+invalidPasswordHistoryMessage=Ugyldig passord: kan ikke v\u00E6re likt noen av de {0} foreg\u00E5ende passordene.
+
+locale_ca=Catal\u00E0
+locale_de=Deutsch
+locale_en=English
+locale_es=Espa\u00F1ol
+locale_fr=Fran\u00e7ais
+locale_it=Italian
+locale_ja=\u65E5\u672C\u8A9E
+locale_no=Norsk
+locale_pt-BR=Portugu\u00EAs (Brasil)
+locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
diff --git a/themes/src/main/resources/theme/base/account/theme.properties b/themes/src/main/resources/theme/base/account/theme.properties
index 503eda7..deb2dc9 100644
--- a/themes/src/main/resources/theme/base/account/theme.properties
+++ b/themes/src/main/resources/theme/base/account/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,pt-BR,ru
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_ca.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_ca.properties
index 02a307a..0025c88 100755
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_ca.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_ca.properties
@@ -218,8 +218,8 @@ assertion-consumer-post-binding-url=Assertion Consumer Service POST Binding URL
 assertion-consumer-post-binding-url.tooltip=SAML POST Binding URL for the client''s assertion consumer service (login responses).  You can leave this blank if you do not have a URL for this binding.
 assertion-consumer-redirect-binding-url=Assertion Consumer Service Redirect Binding URL
 assertion-consumer-redirect-binding-url.tooltip=Assertion Consumer Service Redirect Binding URL
-logout-service-binding-post-url=URL d''enlla\u00E7 SAML POST per a la desconnexi\u00F3
-logout-service-binding-post-url.tooltip=URL d''enlla\u00E7 SAML POST per a la desconnexi\u00F3 \u00FAnica del client. Pots deixar-ho en blanc si est\u00E0s fent servir un enlla\u00E7 diferent.
+logout-service-post-binding-url=URL d''enlla\u00E7 SAML POST per a la desconnexi\u00F3
+logout-service-post-binding-url.tooltip=URL d''enlla\u00E7 SAML POST per a la desconnexi\u00F3 \u00FAnica del client. Pots deixar-ho en blanc si est\u00E0s fent servir un enlla\u00E7 diferent.
 logout-service-redir-binding-url=URL d''enlla\u00E7 SAML de redirecci\u00F3 per a la desconnexi\u00F3
 logout-service-redir-binding-url.tooltip=URL d''enlla\u00E7 SAML de redirecci\u00F3 per a la desconnexi\u00F3 \u00FAnica del client. Pots deixar-ho en blanc si est\u00E0s fent servir un enlla\u00E7 diferent.
 
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 02c7a70..2ebed9f 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -236,14 +236,20 @@ idp-sso-relay-state=IDP Initiated SSO Relay State
 idp-sso-relay-state.tooltip=Relay state you want to send with SAML request when you want to do IDP Initiated SSO.
 web-origins=Web Origins
 web-origins.tooltip=Allowed CORS origins. To permit all origins of Valid Redirect URIs add '+'. To permit all origins add '*'.
+fine-oidc-endpoint-conf=Fine Grain OpenID Connect Configuration
+fine-oidc-endpoint-conf.tooltip=Expand this section to configure advanced settings of this client related to OpenID Connect protocol
+user-info-signed-response-alg=User Info Signed Response Algorithm
+user-info-signed-response-alg.tooltip=JWA algorithm used for signed User Info Endpoint response. If set to 'unsigned', then User Info Response won't be signed and will be returned in application/json format.
+request-object-signature-alg=Request Object Signature Algorithm
+request-object-signature-alg.tooltip=JWA algorithm, which client needs to use when sending OIDC request object specified by 'request' or 'request_uri' parameters. If set to 'any', then Request object can be signed by any algorithm (including 'none' ).
 fine-saml-endpoint-conf=Fine Grain SAML Endpoint Configuration
 fine-saml-endpoint-conf.tooltip=Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.
 assertion-consumer-post-binding-url=Assertion Consumer Service POST Binding URL
 assertion-consumer-post-binding-url.tooltip=SAML POST Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.
 assertion-consumer-redirect-binding-url=Assertion Consumer Service Redirect Binding URL
 assertion-consumer-redirect-binding-url.tooltip=SAML Redirect Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.
-logout-service-binding-post-url=Logout Service POST Binding URL
-logout-service-binding-post-url.tooltip=SAML POST Binding URL for the client's single logout service. You can leave this blank if you are using a different binding
+logout-service-post-binding-url=Logout Service POST Binding URL
+logout-service-post-binding-url.tooltip=SAML POST Binding URL for the client's single logout service. You can leave this blank if you are using a different binding
 logout-service-redir-binding-url=Logout Service Redirect Binding URL
 logout-service-redir-binding-url.tooltip=SAML Redirect Binding URL for the client's single logout service. You can leave this blank if you are using a different binding.
 
@@ -312,7 +318,7 @@ available-roles=Available Roles
 add-selected=Add selected
 associated-roles=Associated Roles
 composite.associated-realm-roles.tooltip=Realm level roles associated with this composite role.
-composite.available-realm-roles.tooltip=Realm level roles associated with this composite role.
+composite.available-realm-roles.tooltip=Realm level roles that you can associate to this composite role.
 remove-selected=Remove selected
 client-roles=Client Roles
 select-client-to-view-roles=Select client to view roles for client
@@ -560,7 +566,7 @@ realm-default-roles.tooltip=Realm level roles assigned to new users.
 default.available-roles-client.tooltip=Roles from this client that are assignable as a default.
 client-default-roles=Client Default Roles
 client-default-roles.tooltip=Roles from this client assigned as a default role.
-composite.available-roles.tooltip=Realm level roles associated with this composite role.
+composite.available-roles.tooltip=Realm level roles that you can associate to this composite role.
 composite.associated-roles.tooltip=Realm level roles associated with this composite role.
 composite.available-roles-client.tooltip=Roles from this client that you can associate to this composite role.
 composite.associated-roles-client.tooltip=Client roles associated with this composite role.
@@ -684,7 +690,7 @@ ldap.custom-user-ldap-filter.tooltip=Additional LDAP Filter for filtering search
 search-scope=Search Scope
 ldap.search-scope.tooltip=For one level, we search for users just in DNs specified by User DNs. For subtree, we search in whole of their subtree. See LDAP documentation for more details
 use-truststore-spi=Use Truststore SPI
-ldap.use-truststore-spi.tooltip=Specifies whether LDAP connection will use the truststore SPI with the truststore configured in keycloak-server.json. 'Always' means that it will always use it. 'Never' means that it won't use it. 'Only for ldaps' means that it will use if your connection URL use ldaps. Note even if keycloak-server.json is not configured, the default Java cacerts or certificate specified by 'javax.net.ssl.trustStore' property will be used.
+ldap.use-truststore-spi.tooltip=Specifies whether LDAP connection will use the truststore SPI with the truststore configured in standalone.xml/domain.xml. 'Always' means that it will always use it. 'Never' means that it won't use it. 'Only for ldaps' means that it will use if your connection URL use ldaps. Note even if standalone.xml/domain.xml is not configured, the default Java cacerts or certificate specified by 'javax.net.ssl.trustStore' property will be used.
 connection-pooling=Connection Pooling
 ldap.connection-pooling.tooltip=Does Keycloak should use connection pooling for accessing LDAP server
 ldap.pagination.tooltip=Does the LDAP server support pagination.
@@ -802,6 +808,7 @@ top-level-flow-type.tooltip=What kind of top level flow is it? Type 'client' is 
 create-execution-flow=Create Execution Flow
 flow-type=Flow Type
 flow.form.type=form
+flow.generic.type=generic
 flow-type.tooltip=What kind of form is it
 form-provider=Form Provider
 default-groups.tooltip=Newly created or registered users will automatically be added to these groups
@@ -1028,7 +1035,7 @@ authz-policy-logic.tooltip=The logic dictates how the policy decision should be 
 authz-policy-apply-policy=Apply Policy
 authz-policy-apply-policy.tooltip=Specifies all the policies that must be applied to the scopes defined by this policy or permission.
 authz-policy-decision-strategy=Decision Strategy
-authz-policy-decision-strategy.tooltip=The decision strategy dictates how the policies associated with a given policy are evaluated and how a final decision is obtained. 'Affirmative' means that at least one policy must evaluate to a positive decision in order to the overall decision be also positive. 'Unanimous' means that all policies must evaluate to a positive decision in order to the overall decision be also positive. 'Consensus' means that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, the final decision will be negative.
+authz-policy-decision-strategy.tooltip=The decision strategy dictates how the policies associated with a given permission are evaluated and how a final decision is obtained. 'Affirmative' means that at least one policy must evaluate to a positive decision in order to the overall decision be also positive. 'Unanimous' means that all policies must evaluate to a positive decision in order to the overall decision be also positive. 'Consensus' means that the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative is the same, the final decision will be negative.
 authz-policy-decision-strategy-affirmative=Affirmative
 authz-policy-decision-strategy-unanimous=Unanimous
 authz-policy-decision-strategy-consensus=Consensus
@@ -1051,6 +1058,16 @@ authz-add-time-policy=Add Time Policy
 authz-policy-time-not-before.tooltip=Defines the time before which the policy MUST NOT be granted. Only granted if current date/time is after or equal to this value.
 authz-policy-time-not-on-after=Not On or After
 authz-policy-time-not-on-after.tooltip=Defines the time after which the policy MUST NOT be granted. Only granted if current date/time is before or equal to this value.
+authz-policy-time-day-month=Day of Month
+authz-policy-time-day-month.tooltip=Defines the day of month before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the day of month before/equal which the policy MUST be granted. In this case, the policy would be granted if current day of month is between/equal the two values you provided.
+authz-policy-time-month=Month
+authz-policy-time-month.tooltip=Defines the month before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the month before/equal which the policy MUST be granted. In this case, the policy would be granted if current month is between/equal the two values you provided.
+authz-policy-time-year=Year
+authz-policy-time-year.tooltip=Defines the year before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the year before/equal which the policy MUST be granted. In this case, the policy would be granted if current year is between/equal the two values you provided.
+authz-policy-time-hour=Hour
+authz-policy-time-hour.tooltip=Defines the hour before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the hour before/equal which the policy MUST be granted. In this case, the policy would be granted if current hour is between/equal the two values you provided.
+authz-policy-time-minute=Minute
+authz-policy-time-minute.tooltip=Defines the minute before/equal which policy MUST be granted. You can also provide a range period by filling the second field with the minute before/equal which the policy MUST be granted. In this case, the policy would be granted if current minute is between/equal the two values you provided.
 
 # Authz Drools Policy Detail
 authz-add-drools-policy=Add Drools Policy
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_es.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_es.properties
index 2a1807c..fb17ff6 100755
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_es.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_es.properties
@@ -218,8 +218,8 @@ assertion-consumer-post-binding-url=Assertion Consumer Service POST Binding URL
 assertion-consumer-post-binding-url.tooltip=SAML POST Binding URL for the client''s assertion consumer service (login responses).  You can leave this blank if you do not have a URL for this binding.
 assertion-consumer-redirect-binding-url=Assertion Consumer Service Redirect Binding URL
 assertion-consumer-redirect-binding-url.tooltip=Assertion Consumer Service Redirect Binding URL
-logout-service-binding-post-url=URL de enlace SAML POST para la desconexi\u00F3n
-logout-service-binding-post-url.tooltip=URL de enlace SAML POST para la desconexi\u00F3n \u00FAnica del cliente. Puedes dejar esto en blanco si est\u00E1s usando un enlace distinto.
+logout-service-post-binding-url=URL de enlace SAML POST para la desconexi\u00F3n
+logout-service-post-binding-url.tooltip=URL de enlace SAML POST para la desconexi\u00F3n \u00FAnica del cliente. Puedes dejar esto en blanco si est\u00E1s usando un enlace distinto.
 logout-service-redir-binding-url=URL de enlace SAML de redirecci\u00F3n para la desconexi\u00F3n
 logout-service-redir-binding-url.tooltip=URL de enlace SAML de redirecci\u00F3n para la desconexi\u00F3n \u00FAnica del cliente. Puedes dejar esto en blanco si est\u00E1s usando un enlace distinto.
 
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_fr.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_fr.properties
index 93e7b14..b923234 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_fr.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_fr.properties
@@ -27,7 +27,7 @@ sslRequired.option.all=toutes les requ\u00eates
 sslRequired.option.external=les requ\u00eates externes
 sslRequired.option.none=aucun
 sslRequired.tooltip=Si le HTTPS est requis ?  ''aucun'' signifie que le HTTPS n''est requis pour aucune adresse IP cliente. ''les requ\u00eates externes'' signifie que localhost et les adresses IP priv\u00e9es peuvent acc\u00e9der sans HTTPS.  ''toutes les requ\u00eates'' signifie que le protocole HTTPS est obligatoire pour toutes les adresses IP.
-publicKey=Clef publique key
+publicKey=Clef publique
 gen-new-keys=Cr\u00e9ation de nouvelle clef 
 certificate=Certificat
 host=H\u00f4te
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_ja.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_ja.properties
new file mode 100644
index 0000000..f99e168
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_ja.properties
@@ -0,0 +1,1121 @@
+# encoding: utf-8
+consoleTitle=Keycloak 管理コンソール
+
+# Common messages
+enabled=有効
+name=名前
+displayName=表示名
+displayNameHtml=HTML 表示名
+save=保存
+cancel=キャンセル
+onText=オン
+offText=オフ
+client=クライアント
+clients=クライアント
+clear=クリア
+selectOne=1つ選択...
+
+true=はい
+false=いいえ
+
+endpoints=エンドポイント
+
+# Realm settings
+realm-detail.enabled.tooltip=有効の場合は、ユーザーとクライアントはこのレルムのみアクセス可能になります
+realm-detail.oidc-endpoints.tooltip=OpenID Connect エンドポイントの設定を表示します。
+registrationAllowed=ユーザー登録
+registrationAllowed.tooltip=登録ページの有効/無効。ログインページに登録のリンクも表示されるようになります。
+registrationEmailAsUsername=Eメールをユーザー名とする
+registrationEmailAsUsername.tooltip=有効の場合は、登録フォームにおいてユーザー名フィールドが非表示なり、Eメールが新規ユーザーのユーザー名として使われます。
+editUsernameAllowed=ユーザー名の編集
+editUsernameAllowed.tooltip=有効の場合はユーザー名フィールドが編集可能になり、そうでない場合は読み取り専用になります。
+resetPasswordAllowed=パスワード忘れ
+resetPasswordAllowed.tooltip=クレデンシャルを忘れてしまった場合にクリックするリンクをログインページに表示します。
+rememberMe=ログイン状態の保存
+rememberMe.tooltip=セッションの有効期限が切れるまではブラウザーの再起動でもログイン状態を保存するチェックボックスをログインページに表示します。
+verifyEmail=Eメールの確認
+verifyEmail.tooltip=初回ログイン時にメールアドレスの確認をユーザーに要求します。
+sslRequired=SSL の要求
+sslRequired.option.all=全てのリクエスト
+sslRequired.option.external=外部リクエスト
+sslRequired.option.none=なし
+sslRequired.tooltip=HTTPS は必須ですか? 「なし」 は HTTPS がどのクライアント IP アドレスにも要求されないことを意味します。 「外部リクエスト」 はローカルホストとプライベート IP アドレスは HTTPS なしでアクセスできることを意味します。 「すべてのリクエスト」 は HTTPS がすべての IP アドレスに要求されることを意味します。
+publicKey=公開鍵
+privateKey=秘密鍵
+gen-new-keys=新しい鍵を生成する
+certificate=証明書
+host=ホスト
+smtp-host=SMTP ホスト
+port=ポート
+smtp-port=SMTP ポート (デフォルトは25)
+from=差出人
+sender-email-addr=送信者のメールアドレス
+enable-ssl=SSL の有効
+enable-start-tls=StartTLS の有効
+enable-auth=認証の有効
+username=ユーザー名
+login-username=ログインユーザー名
+password=パスワード
+login-password=ログインパスワード
+login-theme=ログインテーマ
+login-theme.tooltip=ログイン、TOTP、グラント、登録、パスワード忘れ画面のテーマを選択します。
+account-theme=アカウントテーマ
+account-theme.tooltip=ユーザーアカウント管理画面のテーマを選択します。
+admin-console-theme=管理コンソールテーマ
+select-theme-admin-console=管理コンソールのテーマを選択します。
+email-theme=Eメールテーマ
+select-theme-email=サーバーから送信されるEメールのテーマを選択します。
+i18n-enabled=国際化の有効
+supported-locales=サポートされるロケール
+supported-locales.placeholder=ロケールを入力し Enter キーを押してください
+default-locale=デフォルトロケール
+realm-cache-clear=レルムキャッシュ
+realm-cache-clear.tooltip=レルムキャッシュからすべてのエントリをクリアする (すべてのレルムのエントリをクリアします)
+user-cache-clear=ユーザーキャッシュ
+user-cache-clear.tooltip=ユーザーキャッシュからすべてのエントリを削除します (すべてのレルムのエントリをクリアします)
+revoke-refresh-token=リフレッシュトークンの取り消し
+revoke-refresh-token.tooltip=有効の場合は、リフレッシュトークンは1回のみ使用可能になります。無効の場合は、リフレッシュトークンは使用されても取り消しされず、何度でも使用可能になります。
+sso-session-idle=SSO セッションアイドル
+seconds=秒
+minutes=分
+hours=時
+days=日
+sso-session-max=SSO セッション最大
+sso-session-idle.tooltip=セッションの有効期限が切れるまでのアイドル時間です。セッションが有効期限切れの際はトークンとブラウザーセッションは無効化されます。
+sso-session-max.tooltip=セッションの有効期限が切れるまでの最大時間です。セッションが有効期限切れの際はトークンとブラウザーセッションは無効化されます。
+offline-session-idle=オフラインセッションアイドル
+offline-session-idle.tooltip=セッションの有効期限が切れるまでのオフライン時間です。この期限内に少なくとも1回はオフライントークンを使用してリフレッシュしないと、オフラインセッションは有効期限切れとなります。
+access-token-lifespan=アクセストークン生存期間
+access-token-lifespan.tooltip=アクセストークンが有効期限切れとなる最大時間です。この値は SSO タイムアウトと比べて短くすることをお勧めします。
+access-token-lifespan-for-implicit-flow=Implicit Flow におけるアクセストークン生存期間
+access-token-lifespan-for-implicit-flow.tooltip=OpenID Connect Implicit Flow で発行されたアクセストークンが有効期限切れとなる最大時間です。この値は SSO タイムアウトより短くすることをお勧めします。 Implicit Flow ではトークンを更新することはありませんので、 「アクセストークン生存期間」 とは異なる別々のタイムアウト設定を設けています。
+client-login-timeout=クライアントのログインタイムアウト
+client-login-timeout.tooltip=クライアントがアクセストークンプロトコルを完了するまでの最大時間です。これは通常は1分にすべきです。
+login-timeout=ログインタイムアウト
+login-timeout.tooltip=ユーザーがログインを完了するまでの最大時間です。これは30分以上と比較的長くすることをお勧めします。
+login-action-timeout=ログインアクションタイムアウト
+login-action-timeout.tooltip=ユーザーがパスワードの更新や TOTP の設定のようなログインに関係するアクションを完了するまでの最大時間です。これは5分以上と比較的長くすることをお勧めします。
+headers=ヘッダー
+brute-force-detection=ブルートフォースの検出
+x-frame-options=X-Frame-Options
+x-frame-options-tooltip=デフォルト値では別のオリジンの IFrame からの読み込みを防ぎます (詳細はラベルをクリックしてください)
+content-sec-policy=Content-Security-Policy
+content-sec-policy-tooltip=デフォルト値では別のオリジンの IFrame からの読み込みを防ぎます (詳細はラベルをクリックしてください)
+content-type-options=X-Content-Type-Options
+content-type-options-tooltip=デフォルト値では Internet Explorer と Google Chrome に対して、宣言された content-type を避けてレスポンスの MIME-sniffing を行うことを防ぎます (詳細はラベルをクリックしてください) 
+max-login-failures=最大ログイン失敗回数
+max-login-failures.tooltip=検出するまでの失敗回数です。
+wait-increment=連続失敗時の待機時間
+wait-increment.tooltip=失敗回数が閾値に達した場合、どれくらいの時間ユーザーはロックアウトされるか設定します。
+quick-login-check-millis=クイックログイン試行間のミリ秒数チェック
+quick-login-check-millis.tooltip=クイックログイン失敗があまりにも頻繁に発生した場合は、ユーザーをロックアウトします。
+min-quick-login-wait=クイックログイン失敗時の最小待機時間
+min-quick-login-wait.tooltip=クイックログイン失敗後にどれくらいの時間待機するか設定します。
+max-wait=最大待機時間
+max-wait.tooltip=ユーザーがロックアウトされる最大待機時間を設定します。
+failure-reset-time=ログイン失敗回数のリセット時間
+failure-reset-time.tooltip=いつ失敗回数がリセットされるか設定します。
+realm-tab-login=ログイン
+realm-tab-keys=鍵
+realm-tab-email=Eメール
+realm-tab-themes=テーマ
+realm-tab-cache=キャッシュ
+realm-tab-tokens=トークン
+realm-tab-client-initial-access=初期アクセストークン
+realm-tab-security-defenses=セキュリティ防御
+realm-tab-general=一般
+add-realm=レルムの追加
+
+#Session settings
+realm-sessions=レルムセッション
+revocation=取り消し
+logout-all=すべてログアウトする
+active-sessions=有効なセッション
+sessions=セッション
+not-before=この日時より前
+not-before.tooltip=この日時より前に発行されたトークンを取り消します。
+set-to-now=現在日時を設定
+push=プッシュ
+push.tooltip=管理URLを持つすべてのクライアントに対して、新しい取り消しポリシーを通知します。
+
+#Protocol Mapper
+usermodel.prop.label=プロパティ
+usermodel.prop.tooltip=UserModel インタフェースのプロパティメソッドの名前です。例えば、 「email」 の値は UserModel.getEmail() メソッドを参照しています。
+usermodel.attr.label=ユーザー属性
+usermodel.attr.tooltip=格納されるユーザー属性名、UserMode.attribute マップ内の属性名です。
+userSession.modelNote.label=ユーザーセッションノート
+userSession.modelNote.tooltip=UserSessionModel.note マップ内のユーザーセッションノート名です。
+multivalued.label=マルチバリュー
+multivalued.tooltip=属性がマルチバリューをサポートしているかどうかを示します。サポートしている場合は、この属性のすべての値リストがクレームとして設定されます。サポートしていない場合は、最初の値だけがクレームとして設定されます。
+selectRole.label=ロールの選択
+selectRole.tooltip=左側にあるテキストボックスにロールを入力するか、ブラウズして必要なロールを選択するためにこのボタンをクリックしてください。
+tokenClaimName.label=トークンクレーム名
+tokenClaimName.tooltip=トークン内に挿入するクレームの名前を設定します。 「address.street」 のように完全修飾名で設定します。この場合、ネストされた JSON オブジェクトが作成されます。
+jsonType.label=クレーム JSON タイプ
+jsonType.tooltip=トークンへの JSON クレーム の追加で使用される JSON タイプを設定します。 long、int、boolean、String が有効な値です。
+includeInIdToken.label=ID トークンに追加
+includeInIdToken.tooltip=クレームを ID トークンに追加すべきかどうかを設定します。
+includeInAccessToken.label=アクセストークンに追加
+includeInAccessToken.tooltip=クレームをアクセストークンに追加すべきかどうかを設定します。
+includeInUserInfo.label=UserInfo に追加
+includeInUserInfo.tooltip=クレームを UserInfo に追加すべきかどうかを設定します。
+usermodel.clientRoleMapping.clientId.label=クライアント ID
+usermodel.clientRoleMapping.clientId.tooltip=ロールマッピング用のクライアント ID
+usermodel.clientRoleMapping.rolePrefix.label=クライアントロールのプレフィックス
+usermodel.clientRoleMapping.rolePrefix.tooltip=各クライアントロールのプレフィックスを設定します (オプション)。
+usermodel.realmRoleMapping.rolePrefix.label=レルムロールのプレフィックス
+usermodel.realmRoleMapping.rolePrefix.tooltip=各レルムロールのプレフィックスを設定します (オプション)。
+
+# client details
+clients.tooltip=クライアントとはレルム内の信頼されたブラウザーアプリケーションや Web サービスです。これらのクライアントはログインを要求することができます。また、クライアント固有のロールを定義することができます。
+search.placeholder=検索...
+create=作成
+import=インポート
+client-id=クライアント ID
+base-url=ベース URL
+actions=アクション
+not-defined=未定義
+edit=編集
+delete=削除
+no-results=結果がありません
+no-clients-available=使用可能なクライアントはありません
+add-client=クライアントの追加
+select-file=ファイルを選択
+view-details=詳細を参照
+clear-import=インポートをクリア
+client-id.tooltip=URI とトークンで参照される ID を指定します。例えば 「my-client」 です。 SAML においては 期待される AuthnRequest の Issuer の値になります。
+client.name.tooltip=クライアントの表示名を指定します。例えば、 「My Client」 です。ローカライズ用のキーもサポートしています。例\: ${my_client}
+client.enabled.tooltip=無効なクライアントはログインを開始したり、アクセストークンを取得したりすることはできません。
+consent-required=同意が必要
+consent-required.tooltip=有効の場合は、ユーザーはクライアントアクセスに同意する必要があります。
+client-protocol=クライアントプロトコル
+client-protocol.tooltip=「OpenID Connect」 は、認可サーバーによって実行される認証を元にして、エンドユーザーのアイデンティティを確認するクライアントです。 「SAML」 は、クロスドメインのシングルサインオン (SSO) を含むWeb ベースの認証と認可シナリオを可能にし、情報を渡すためにアサーションを含むセキュリティトークンを使用します。
+access-type=アクセスタイプ
+access-type.tooltip=「Confidential」 クライアントはログインプロトコルの開始するためにシークレットを必要とします。 「Public」 クライアントはシークレットを必要としません。 「Bearer-only」 クライアントはログインを開始することはない Web サービスです。
+standard-flow-enabled=Standard Flow の有効
+standard-flow-enabled.tooltip=OpenID Connect の標準的な、認可コードによるリダイレクトベースの認証を有効にします。 OpenID Connect または OAuth2 の仕様における 「Authorization Code Flow」 のサポートを有効にします。
+implicit-flow-enabled=Implicit Flow の有効
+implicit-flow-enabled.tooltip=OpenID Connect の認可コードなしのリダイレクトベース認証のサポートを有効にします。OpenID Connect または OAuth2 の仕様における 「Implicit Flow」 のサポートを有効にします。
+direct-access-grants-enabled=ダイレクトアクセスグラントの有効
+direct-access-grants-enabled.tooltip=ダイレクトアクセスグラントのサポートを有効にします。これは、アクセストークンの取得のために Keycloak サーバーとユーザーのユーザー名/パスワードで直接アクセスを行います。OAuth2 の仕様における 「リソースオーナーパスワードクレデンシャルグラント」 のサポートを有効にします。
+service-accounts-enabled=サービスアカウントの有効
+service-accounts-enabled.tooltip=Keycloak にこのクライアントを認証し、このクライアント専用のアクセストークンの取得ができるようになります。OAuth2 の仕様における 「クライアントクレデンシャルグラント」 のサポートを有効にします。
+include-authnstatement=AuthnStatement を含める
+include-authnstatement.tooltip=認証方式とタイムスタンプを含めたステートメントをログインレスポンスに含めるべきか設定します。
+sign-documents=ドキュメントを署名する
+sign-documents.tooltip=SAML ドキュメントをレルムで署名すべきか設定します。
+sign-assertions=アサーションを署名する
+sign-assertions.tooltip=SAML ドキュメント内のアサーションを署名すべきか設定します。もしドキュメントが既に署名済みの場合は、この設定は不要です。
+signature-algorithm=署名アルゴリズム
+signature-algorithm.tooltip=ドキュメントの署名に使用する署名アルゴリズムです。
+canonicalization-method=正規化方式
+canonicalization-method.tooltip=XML署名の正規化方式 (Canonicalization Method) を設定します。
+encrypt-assertions=アサーションを暗号化する
+encrypt-assertions.tooltip=SAML アサーションをクライアントの公開鍵で AES を使い暗号化すべきか設定します。
+client-signature-required=クライアント署名が必須
+client-signature-required.tooltip=クライアントは SAML リクエストとレスポンスを署名しますか? それらを検証すべきか設定します。
+force-post-binding=POST Binding を強制
+force-post-binding.tooltip=レスポンスに常に POST Binding を使用します。
+front-channel-logout=フロントチャンネルログアウト
+front-channel-logout.tooltip=有効の場合は、ログアウトはクライアントへのブラウザーリダイレクトが必要になります。無効の場合は、サーバーはログアウトのバックグラウンド呼び出しを行います。
+force-name-id-format=Name ID フォーマットを強制
+force-name-id-format.tooltip=要求された NameID サブジェクトフォーマットを無視し、管理コンソールで設定された物を使用します。
+name-id-format=Name ID フォーマット
+name-id-format.tooltip=サブジェクトに使用する Name ID フォーマットを設定します。
+root-url=ルート URL
+root-url.tooltip=相対 URL に追加するルート URL を設定します。
+valid-redirect-uris=有効なリダイレクト URI
+valid-redirect-uris.tooltip=ログインまたはログインの成功後にブラウザーがリダイレクト可能とする、有効な URI パターンを設定します。単純なワイルドカード、つまり 「http://example.com/*」 が使用可能です。相対パス、つまり 「/my/relative/path/*」 も指定可能です。相対パスはクライアントのルート URL を基準とします。または、未指定の場合は認証サーバーのルート URL が使用されます。SAML では、ログインリクエストに埋め込まれたコンシューマサービスの URL に依存している場合は、有効な URI パターンを設定する必要があります。
+base-url.tooltip=認証サーバーがクライアントへのリダイレクトまたは戻るリンクを必要とする際に使用するデフォルト URL を設定します。
+admin-url=管理 URL
+admin-url.tooltip=クライアントの管理インタフェースの URL を設定します。クライアントがアダプターの REST API をサポートしている場合に設定してください。この REST API により、認証サーバーは取り消しポリシーや他の管理タスクをプッシュすることができます。通常、クライアントのベース URL を設定します。
+master-saml-processing-url=SAML を処理するマスター URL
+master-saml-processing-url.tooltip=設定された場合は、この URL が SP のアサーションコンシューマおよびシングルログアウトサービスの両方の Binding に使われます。これは、SAML エンドポイントの詳細設定にある各 Binding やサービスの設定にて個別に上書きすることができます。
+idp-sso-url-ref=IDP Initiated SSO の URL Name
+idp-sso-url-ref.tooltip=IDP Initiated SSO を行う際にクライアントを参照するための URL フラグメント名を設定します。空にすると IDP Initiated SSO は無効になります。ブラウザーから参照する URL は 「{server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}」 になります。
+idp-sso-relay-state=IDP Initiated SSO の RelayState
+idp-sso-relay-state.tooltip=IDP Initiated SSO を行う際の SAML リクエストで送信したい RelayState を設定します。
+web-origins=Web オリジン
+web-origins.tooltip=許可される CORS オリジンを設定します。有効なリダイレクト URI のすべてのオリジンを許可するには 「+」 を追加してください。すべてのオリジンを許可するには 「*」 を追加してください。
+fine-saml-endpoint-conf=SAML エンドポイントの詳細設定
+fine-saml-endpoint-conf.tooltip=アサーションコンシューマおよびシングルログアウトサービスの正確な URL を設定するにはこのセクションを開きます。
+assertion-consumer-post-binding-url=アサーションコンシューマサービスの POST Binding URL
+assertion-consumer-post-binding-url.tooltip=アサーションコンシューマサービス (ログインレスポンス) の SAML POST Binding URL を設定します。この Binding のための URL がない場合は空でよいです。
+assertion-consumer-redirect-binding-url=アサーションコンシューマサービスの Redirect Binding URL
+assertion-consumer-redirect-binding-url.tooltip=アサーションコンシューマサービス (ログインレスポンス) の SAML Redirect Binding URL を設定します。この Binding のための URL がない場合は空でよいです。
+logout-service-post-binding-url=ログアウトサービスの POST Binding URL
+logout-service-post-binding-url.tooltip=シングルログアウトサービスの SAML POST Binding URLを設定します。異なる Binding を使用している場合は空でよいです。
+logout-service-redir-binding-url=ログアウトサービスの Redirect Binding URL
+logout-service-redir-binding-url.tooltip=シングルログアウトサービスの SAML Redirect Binding URLを設定します。異なる Binding を使用している場合は空でよいです。
+
+# client import
+import-client=クライアントのインポート
+format-option=フォーマットオプション
+select-format=フォーマットを選択
+import-file=ファイルをインポート
+
+# client tabs
+settings=設定
+credentials=クレデンシャル
+saml-keys=SAML 鍵
+roles=ロール
+mappers=マッパー
+mappers.tooltip=プロトコルマッパーはトークンやドキュメントの変換を行います。ユーザーデータをプロトコルのクレームにマッピングしたり、クライアントと認証サーバー間の任意のリクエストを単に変換したりすることができます。
+scope=スコープ
+scope.tooltip=スコープマッピングはクライアントに要求されたアクセストークン内に含まれるユーザーのロールマッピングを制限することができます。
+sessions.tooltip=このクライアントの有効なセッションを参照します。どのユーザーがアクティブでいつログインしたかを見ることができます。
+offline-access=オフラインアクセス
+offline-access.tooltip=このクライアントのオフラインセッションを参照します。オフライントークンをどのユーザーがいつ取得したかを見ることができます。このクライアントのすべてのトークンを取り消すには、取り消しタブを開き、 「この日時より前」 に現在日時を設定してください。
+clustering=クラスタリング
+installation=インストール
+installation.tooltip=様々なクライアントアダプターの設定フォーマットを生成するヘルパーユーティリティです。生成したものをダウンロードまたはカットアンドペーストしてクライアントに設定することができます。
+service-account-roles=サービスアカウントロール
+service-account-roles.tooltip=このクライアント専用のサービスアカウントのロールマッピングを認証できるようにします。
+
+# client credentials
+client-authenticator=クライアント認証
+client-authenticator.tooltip=Keycloak サーバーに対してこのクライアントの認証に使用するクライアント認証方式を設定します。
+certificate.tooltip=クライアントで発行され、キーストアの秘密鍵で署名された JWT を検証するためのクライアント証明書です。
+publicKey.tooltip=クライアントで発行され、秘密鍵で署名された JWT を検証するための公開鍵です。
+no-client-certificate-configured=クライアント証明書が設定されていません
+gen-new-keys-and-cert=新しい鍵と証明書を生成
+import-certificate=証明書をインポート
+gen-client-private-key=クライアントの秘密鍵の生成
+generate-private-key=秘密鍵の生成
+archive-format=アーカイブ形式
+archive-format.tooltip=Java キーストアまたは PKCS12 アーカイブ形式
+key-alias=キーエイリアス
+key-alias.tooltip=秘密鍵と証明書のアーカイブエイリアスです。
+key-password=鍵のパスワード
+key-password.tooltip=アーカイブ内の秘密鍵にアクセスするためのパスワード
+store-password=ストアのパスワード
+store-password.tooltip=アーカイブ自身にアクセスするためのパスワード
+generate-and-download=生成 & ダウンロード
+client-certificate-import=クライアント証明書のインポート
+import-client-certificate=クライアント証明書のインポート
+jwt-import.key-alias.tooltip=証明書のアーカイブエイリアスです。
+secret=シークレット
+regenerate-secret=シークレットの再生成
+registrationAccessToken=登録用アクセストークン
+registrationAccessToken.regenerate=登録用アクセストークンの再生成
+registrationAccessToken.tooltip=登録用アクセストークンにより、クライアントはクライアント登録サービスにアクセスできます。
+add-role=ロールの追加
+role-name=ロール名
+composite=複合
+description=説明
+no-client-roles-available=使用可能なクライアントロールはありません。
+scope-param-required=スコープパラメータが必要
+scope-param-required.tooltip=認可/トークンリクエストの間にロール名のスコープパラメータが使用された場合のみ与えられます。
+composite-roles=複合ロール
+composite-roles.tooltip=このロールがユーザーにアサイン(アサイン解除)された際に、関連するロールが暗黙的にアサイン(アサイン解除)されます。
+realm-roles=レルムロール
+available-roles=使用可能なロール
+add-selected=選択したものを追加
+associated-roles=関連ロール
+composite.associated-realm-roles.tooltip=この複合ロールに関連付けされているレルムレベルのロールです。
+composite.available-realm-roles.tooltip=この複合ロールに関連付け可能なレルムレベルのロールです。
+remove-selected=選択されたものを削除
+client-roles=クライアントロール
+select-client-to-view-roles=ロールを参照するにはクライアントを選択してください
+available-roles.tooltip=この複合ロール関連付け可能なこのクライアントのロールです。
+client.associated-roles.tooltip=この複合ロールに関連付けされているクライアントロールです。
+add-builtin=ビルトインを追加
+category=カテゴリ
+type=タイプ
+no-mappers-available=使用可能なマッパーはありません
+add-builtin-protocol-mappers=ビルトインプロトコルマッパーを追加
+add-builtin-protocol-mapper=ビルトインプロトコルマッパーを追加
+scope-mappings=スコープマッピング
+full-scope-allowed=フルスコープを許可
+full-scope-allowed.tooltip=全ての制限の無効を許可します。
+scope.available-roles.tooltip=スコープにアサイン可能なレルムレベルのロールです。
+assigned-roles=アサイン済みロール
+assigned-roles.tooltip=スコープにアサイン済みのレルムレベルのロールです。
+effective-roles=有効なロール
+realm.effective-roles.tooltip=複合ロールの継承も含めたアサイン済みのレルムレベルのロールです。
+select-client-roles.tooltip=ロールを参照するにはクライアントを選択してください
+assign.available-roles.tooltip=アサイン可能なクライアントロールです。
+client.assigned-roles.tooltip=アサイン済みクライアントロールです。
+client.effective-roles.tooltip=複合ロールより引き継いでいるロールも含めたアサイン済みのクライアントロールです。
+basic-configuration=基本設定
+node-reregistration-timeout=ノード再登録のタイムアウト
+node-reregistration-timeout.tooltip=登録されたクライアントをクラスターノードへ再登録する際の最大時間間隔を設定します。クラスターノードがこの時間内に Keycloak に再登録リクエストを送信しない場合は、Keycloak から登録解除されます。
+registered-cluster-nodes=登録済みクラスターノード
+register-node-manually=ノードを手動で登録
+test-cluster-availability=クラスターの可用性をテスト
+last-registration=最終登録
+node-host=ノードホスト
+no-registered-cluster-nodes=使用可能な登録済みクラスターノードがありません
+cluster-nodes=クラスターノード
+add-node=ノードを追加
+active-sessions.tooltip=このクライントの有効なユーザーセッションの合計数です。
+show-sessions=セッションを表示
+show-sessions.tooltip=有効なセッション数に応じて高負荷なオペレーションになる恐れがありますので注意してください。
+user=ユーザー
+from-ip=From IP
+session-start=セッション開始
+first-page=最初のページ
+previous-page=前のページ
+next-page=次のページ
+client-revoke.not-before.tooltip=この日時より前に発行されたこのクライアント用のトークンを取り消します。
+client-revoke.push.tooltip=管理 URL がこのクライアントに設定されている場合は、クライアントにポリシーをプッシュします。
+select-a-format=フォーマットを選択
+download=ダウンロード
+offline-tokens=オフライントークン
+offline-tokens.tooltip=このクライアントのオフライントークンの合計数です。
+show-offline-tokens=オフライントークンを表示
+show-offline-tokens.tooltip=オフライントークン数に応じて高負荷なオペレーションになる恐れがありますので注意してください。
+token-issued=発行済みトークン
+last-access=最終アクセス
+last-refresh=最終リフレッシュ
+key-export=鍵をエクスポート
+key-import=鍵をインポート
+export-saml-key=SAML 鍵をエクスポート
+import-saml-key=SAML 鍵をインポート
+realm-certificate-alias=レルム証明書エイリアス
+realm-certificate-alias.tooltip=レルム証明書もアーカイブに格納されます。これはそのエイリアスとなります。
+signing-key=署名鍵
+saml-signing-key=SAML 署名鍵です。
+private-key=秘密鍵
+generate-new-keys=新しい鍵を生成
+export=エクスポート
+encryption-key=暗号化鍵
+saml-encryption-key.tooltip=SAML 暗号化鍵です。
+service-accounts=サービスアカウント
+service-account.available-roles.tooltip=サービスアカウントにアサイン可能なレルムレベルのロールです。
+service-account.assigned-roles.tooltip=サービスアカウントにアサイン済みのレルムレベルのロールです。
+service-account-is-not-enabled-for={{client}} のサービスアカウントは有効ではありません
+create-protocol-mappers=プロトコルマッパーを作成
+create-protocol-mapper=プロトコルマッパーを作成
+protocol=プロトコル
+protocol.tooltip=プロトコルです。
+id=ID
+mapper.name.tooltip=マッパーの名前です。
+mapper.consent-required.tooltip=一時的なアクセスを許可する際に、クライアントへの提供データにユーザーの同意を必要とするか設定します。
+consent-text=同意のテキスト
+consent-text.tooltip=同意ページに表示するテキストです。
+mapper-type=マッパータイプ
+mapper-type.tooltip=マッパーのタイプです。
+# realm identity providers
+identity-providers=アイデンティティ プロバイダー
+table-of-identity-providers=アイデンティティ プロバイダーの一覧表
+add-provider.placeholder=プロバイダーを追加...
+provider=プロバイダー
+gui-order=GUI 順序
+first-broker-login-flow=初回ログインフロー
+post-broker-login-flow=ログイン後のフロー
+redirect-uri=リダイレクト URI
+redirect-uri.tooltip=アイデンティティ プロバイダーの設定で使用するリダイレクト URIです。
+alias=エイリアス
+identity-provider.alias.tooltip=エイリアスは一意にアイデンティティ プロバイダーを識別するもので、リダイレクト URI の構築にも使用されます。
+identity-provider.enabled.tooltip=このアイデンティティ プロバイダーの有効/無効を設定します。
+authenticate-by-default=デフォルトで認証
+identity-provider.authenticate-by-default.tooltip=ログイン画面の表示前に、このプロバイダーでデフォルトで認証試行すべきかどうかを示しています。
+store-tokens=トークンの格納
+identity-provider.store-tokens.tooltip=ユーザー認証後のトークン格納の有効/無効を設定します。
+stored-tokens-readable=読み取り可能なトークンを格納
+identity-provider.stored-tokens-readable.tooltip=新しいユーザーが格納されたトークンを読み取り可能かどうかの有効/無効設定です。broker.read-token ロールをアサインします。
+update-profile-on-first-login=初回ログイン時にプロフィールを更新
+on=オン
+on-missing-info=情報不足の場合
+off=オフ
+update-profile-on-first-login.tooltip=初回ログイン時にどのユーザーがプロフィールの更新を必要とするか条件を定義します。
+trust-email=Eメールを信頼
+trust-email.tooltip=有効とした場合は、このレルムでEメールの確認が有効となっている場合でも、このプロバイダーが提供するEメールは確認されなくなります。
+gui-order.tooltip=GUI (例. ログインページ上) でのプロバイダーの表示順序を決める番号を設定します。
+first-broker-login-flow.tooltip=このアイデンティティ プロバイダーでの初回ログイン後に起動させる認証フローのエイリアスです。 「初回ログイン」 という用語は、認証したアイデンティティ プロバイダーアカウントに関連付けられた Keycloak アカウントがまだ存在しない状態であることを意味します。
+post-broker-login-flow.tooltip=このアイデンティティ プロバイダーでの各ログイン後に起動させる認証フローのエイリアスです。このアイデンティティ プロバイダーで認証された各ユーザーの追加の確認 (例えば OTP) を行いたい場合に便利です。このアイデンティティ プロバイダーによるログイン後に追加の Authenticator の起動を行いたくない場合は、空のままとしてください。また、Authenticator の実装では、ClientSession にはアイデンティティ プロバイダーによりユーザーが既に設定されていることに注意してください。
+openid-connect-config=OpenID Connect の設定
+openid-connect-config.tooltip=OIDC SP と 外部 IDP の設定です。
+authorization-url=認可 URL
+authorization-url.tooltip=認可 URL を設定します。
+token-url=トークン URL
+token-url.tooltip=トークン URL を設定します。
+logout-url=ログアウト URL
+identity-provider.logout-url.tooltip=外部 IDP からユーザーのログアウトに使用するセッション終了エンドポイントを設定します。
+backchannel-logout=バックチャンネルログアウト
+backchannel-logout.tooltip=外部 IDP がバックチャンネルログアウトをサポートするどうかを設定します。
+user-info-url=UserInfo URL
+user-info-url.tooltip=UserInfo の URL を設定します。これはオプションです。
+identity-provider.client-id.tooltip=アイデンティティ プロバイダーで登録されているクライアントまたはクライアント識別子を設定します。
+client-secret=クライアントシークレット
+show-secret=シークレットを表示する
+hide-secret=シークレットを隠す
+client-secret.tooltip=アイデンティティ プロバイダーで登録されているクライアントまたはクライアントシークレットを設定します。
+issuer=発行者 (Issuer)
+issuer.tooltip=レスポンス内の発行者の識別子 (Issuer Identifier) を設定します。未設定の場合は、検証は実行されません。
+default-scopes=デフォルトスコープ
+identity-provider.default-scopes.tooltip=認可要求の際に送信されるスコープです。スペース区切りでスコープのリストを設定します。デフォルトは 「openid」 です。
+prompt=プロンプト (prompt)
+unspecified.option=未定義
+none.option=none
+consent.option=consent
+login.option=login
+select-account.option=select_account
+prompt.tooltip=認証サーバーは再認証や同意をエンドユーザーに促すかどうかを指定します。
+validate-signatures=署名検証
+identity-provider.validate-signatures.tooltip=外部 IDP の署名検証の有効/無効を設定します。
+validating-public-key=検証用の公開鍵
+identity-provider.validating-public-key.tooltip=外部 IDP の署名検証に使用する PEM 形式の公開鍵を設定します。
+import-external-idp-config=外部 IDP 設定のインポート
+import-external-idp-config.tooltip=外部 IDP メタデータを設定ファイルよりロード、または URL よりダウンロードして設定します。
+import-from-url=URL よりインポート
+identity-provider.import-from-url.tooltip=リモート IDP ディスカバリディスクリプタよりメタデータをインポートします。
+import-from-file=ファイルよりインポート
+identity-provider.import-from-file.tooltip=ダウンロードした IDP ディスカバリディスクリプタよりメタデータをインポートします。
+saml-config=SAML 設定
+identity-provider.saml-config.tooltip=SAML SP と 外部 IDP の設定です。
+single-signon-service-url=シングルサインオンサービスの URL
+saml.single-signon-service-url.tooltip=認証リクエスト (SAML AuthnRequest) の送信に使用する URL を設定します。
+single-logout-service-url=シングルログアウトサービスの URL
+saml.single-logout-service-url.tooltip=ログアウトリクエストの送信に使用する URL を設定します。
+nameid-policy-format=Name ID ポリシーフォーマット
+nameid-policy-format.tooltip=Name ID フォーマットに対応する URI リファレンスを指定します。デフォルトは urn:oasis:names:tc:SAML:2.0:nameid-format:persistent になります。
+http-post-binding-response=HTTP-POST Binding レスポンス
+http-post-binding-response.tooltip=HTTP-POST Binding を使用してリクエストに応答するかどうかを設定します。オフの場合は、HTTP-REDIRECT Binding が使用されます。
+http-post-binding-for-authn-request=AuthnRequest の HTTP-POST Binding
+http-post-binding-for-authn-request.tooltip=HTTP-POST Binding を使用して AuthnRequest を送信するかどうかを設定します。オフの場合は、HTTP-REDIRECT Binding が使用されます。
+want-authn-requests-signed=AuthnRequest の署名が必要
+want-authn-requests-signed.tooltip=アイデンティティ プロバイダーが署名された AuthnRequest を必要とするかどうかを設定します。
+force-authentication=認証を強制
+identity-provider.force-authentication.tooltip=アイデンティティ プロバイダーが以前のセキュリティコンテキストに頼るのではなく、プレゼンターを直接認証すべきかどうかを設定します。
+validate-signature=署名検証
+saml.validate-signature.tooltip=SAML レスポンスの署名検証の有効/無効を設定します。
+validating-x509-certificate=検証用の X509 証明書
+validating-x509-certificate.tooltip=署名の確認に使用する PEM 形式の証明書を設定します。
+saml.import-from-url.tooltip=リモート IDP の SAML エンティティディスクリプタからメタデータをインポートします。
+social.client-id.tooltip=アイデンティティ プロバイダーで登録されているクライアント識別子を設定します。
+social.client-secret.tooltip=アイデンティティ プロバイダーで登録されているクライアントシークレットを設定します。
+social.default-scopes.tooltip=認可要求の際に送信されるスコープを設定します。設定可能な値、区切り文字、デフォルト値はドキュメントを参照してください。
+key=Key
+stackoverflow.key.tooltip=Stack Overflow のクライアント登録で取得した Key を設定します。
+
+# User federation
+sync-ldap-roles-to-keycloak=LDAP ロールを Keycloak に同期
+sync-keycloak-roles-to-ldap=Keycloak ロールを LDAP に同期
+sync-ldap-groups-to-keycloak=LDAP グループを Keycloak に同期
+sync-keycloak-groups-to-ldap=Keycloak グループを LDAP に同期
+
+realms=レルム
+realm=レルム
+
+identity-provider-mappers=アイデンティティ プロバイダー マッパー
+create-identity-provider-mapper=アイデンティティ プロバイダー マッパーを作成
+add-identity-provider-mapper=アイデンティティ プロバイダー マッパーを追加
+client.description.tooltip=クライアントの説明を指定します。例えば 「タイムシート用のクライアント」 です。ローカライズ用のキーもサポートしています。例\: ${my_client_description}
+
+expires=有効期限
+expiration=有効期限
+expiration.tooltip=トークンの有効期間を指定します。
+count=カウント
+count.tooltip=このトークンを利用してクライアントをいくつ作成可能か指定します。
+remainingCount=残りのカウント
+created=作成日時
+back=戻る
+initial-access-tokens=初期アクセストークン
+initial-access-tokens.tooltip=動的クライアント登録用の初期アクセストークンです。これらのトークン付きのリクエストは任意のホストから送信することができます。
+add-initial-access-tokens=初期アクセストークンを追加
+initial-access-token=初期アクセストークン
+initial-access.copyPaste.tooltip=後からは取得することはできませんので、このページから離れる前に初期アクセストークンをコピー/ペーストしてください。
+continue=続ける
+initial-access-token.confirm.title=初期アクセストークンのコピー
+initial-access-token.confirm.text=後からは取得することはできませんので、初期アクセストークンのコピー & ペーストを行ってください
+no-initial-access-available=使用可能な初期アクセストークンはありません
+
+trusted-hosts-legend=クライアント登録用の信頼されたホスト
+trusted-hosts-legend.tooltip=クライアント登録用に信頼されたホストです。これらのホストからのクライアント登録のリクエストは、初期アクセストークンなしで送信することができます。特定ホストからのクライアント登録数は指定された数に制限することができます。
+no-client-trusted-hosts-available=使用可能な信頼されたホストはありません
+add-client-reg-trusted-host=信頼されたホストの追加
+hostname=ホスト名
+client-reg-hostname.tooltip=完全修飾のホスト名またはIPアドレスです。このホスト/アドレスからのクライアント登録のリクエストは信頼され、新しいクライアント登録が許可されます。
+client-reg-count.tooltip=特定ホストからのクライアント登録リクエストを許可する数です。このリミットに達した場合はリスタートする必要があります。
+client-reg-remainingCount.tooltip=このホストからのクライアント登録リクエストの残りのカウントです。このリミットに達した場合はリスタートする必要があります。
+reset-remaining-count=残りのカウントをリセット
+
+
+client-templates=クライアントテンプレート
+client-templates.tooltip=クライアントテンプレートでは、複数のクライアントで共有する共通設定を定義することができます。
+
+groups=グループ
+
+group.add-selected.tooltip=グループにアサイン可能なレルムロールです。
+group.assigned-roles.tooltip=グループにマッピングされたレルムロールです。
+group.effective-roles.tooltip=マッピングされているすべてのレルムロールです。複合ロールより引き継いでいるロールも含みます。
+group.available-roles.tooltip=このクライアントよりアサイン可能なロールです。
+group.assigned-roles-client.tooltip=マッピングされたこのクライアントのロールです。
+group.effective-roles-client.tooltip=マッピングされたこのクライアントのロールです。複合ロールより引き継いでいるロールも含みます。
+
+default-roles=デフォルトロール
+no-realm-roles-available=使用可能なレルムロールはありません
+
+users=ユーザー
+user.add-selected.tooltip=ユーザーにアサイン可能なレルムロールです。
+user.assigned-roles.tooltip=ユーザーにマッピングされたレルムロールです。
+user.effective-roles.tooltip=マッピングされているすべてのレルムロールです。複合ロールより引き継いでいるロールも含みます。
+user.available-roles.tooltip=このクライアントよりアサイン可能なロールです。
+user.assigned-roles-client.tooltip=マッピングされたこのクライアントのロールです。
+user.effective-roles-client.tooltip=マッピングされたこのクライアントのロールです。複合ロールより引き継いでいるロールも含みます。
+default.available-roles.tooltip=アサイン可能なレルムレベルのロールです。
+realm-default-roles=レルムのデフォルトロール
+realm-default-roles.tooltip=ユーザーにアサインされたレルムレベルのロールです。
+default.available-roles-client.tooltip=デフォルトでアサイン可能なこのクライアントのロールです。
+client-default-roles=クライアントのデフォルトロール
+client-default-roles.tooltip=デフォルトロールとしてアサインされたこのクライアントのロールです。
+composite.available-roles.tooltip=この複合ロールに関連付け可能なレルムレベルのロールです。
+composite.associated-roles.tooltip=この複合ロールに関連付けされているレルムレベルのロールです。
+composite.available-roles-client.tooltip=この複合ロールに関連付け可能なこのクライアントのロールです。
+composite.associated-roles-client.tooltip=この複合ロールに関連付けされているクライアントロールです。
+partial-import=部分インポート
+partial-import.tooltip=部分インポートでは、以前にエクスポートした JSON ファイルよりユーザー、クライアント、およびその他のリソースをインポートすることができます。
+
+file=ファイル
+exported-json-file=エクスポートされた JSON ファイル
+import-from-realm=レルムからインポート
+import-users=ユーザーをインポート
+import-groups=グループをインポート
+import-clients=クライアントをインポート
+import-identity-providers=アイデンティティ プロバイダーをインポート
+import-realm-roles=レルムロールをインポート
+import-client-roles=クライアントロールをインポート
+if-resource-exists=リソースが存在する場合
+fail=失敗
+skip=スキップ
+overwrite=上書き
+if-resource-exists.tooltip=既に存在するリソースをインポートしようとした場合にどうすべきかを指定します。
+
+action=アクション
+role-selector=ロールの選択
+realm-roles.tooltip=選択可能なレルムロールです。
+
+select-a-role=ロールを選択してください
+select-realm-role=レルムロールを選択
+client-roles.tooltip=選択可能なクライアントロールです。
+select-client-role=クライアントロールを選択
+
+client-template=クライアントテンプレート
+client-template.tooltip=設定を引き継ぐクライアントテンプレートを選択します。
+client-saml-endpoint=クライアント SAML エンドポイント
+add-client-template=クライアントテンプレートを追加
+
+manage=管理
+authentication=認証
+user-federation=ユーザーフェデレーション
+user-storage=ユーザーストレージ
+events=イベント
+realm-settings=レルムの設定
+configure=設定
+select-realm=レルムの選択
+add=追加
+
+client-template.name.tooltip=クライアントテンプレートの名前です。レルム内でユニークにする必要があります。
+client-template.description.tooltip=クライアントテンプレートの説明です。
+client-template.protocol.tooltip=このクライアントテンプレートにより、どの SSO プロトコルが提供されるか設定します。
+
+add-user-federation-provider=ユーザー フェデレーション プロバイダーの追加
+add-user-storage-provider=ユーザー ストレージ プロバイダーの追加
+required-settings=必要な設定
+provider-id=プロバイダー ID
+console-display-name=コンソール表示名
+console-display-name.tooltip=管理コンソール内でのリンク表示名を設定します。
+priority=優先度
+priority.tooltip=ユーザーを検索する際のプロバイダーの優先度を設定します。低い順となります。
+sync-settings=同期の設定
+periodic-full-sync=定期的なフル同期
+periodic-full-sync.tooltip=プロバイダーユーザーの Keycloak への定期的なフル同期を有効または無効とすべきかを設定します。
+full-sync-period=フル同期の周期
+full-sync-period.tooltip=フル同期の周期を秒で設定します。
+periodic-changed-users-sync=定期的な変更ユーザーの同期
+periodic-changed-users-sync.tooltip=変更または新規作成されたプロバイダーユーザーの Keycloak への定期的な同期を有効または無効とすべきか設定します。
+changed-users-sync-period=変更ユーザーの同期周期
+changed-users-sync-period.tooltip=変更または新規作成されたプロバイダーユーザーの同期周期を秒で設定します。
+synchronize-changed-users=変更ユーザーを同期
+synchronize-all-users=すべてのユーザーを同期
+kerberos-realm=Kerberos レルム
+kerberos-realm.tooltip=Kerberos レルムの名前を設定します。例えば、 FOO.ORG です。
+server-principal=サーバープリンシパル
+server-principal.tooltip=サーバー、ドメイン名を含む HTTP サービスのサービスプリンシパルのフルネームを設定します。例えば、 HTTP/host.foo.org@FOO.ORG です。
+keytab=KeyTab
+keytab.tooltip=サーバープリンシパルのクレデンシャルを含む Kerberos の KeyTab ファイルを設定します。例えば、/etc/krb5.keytab です。
+debug=デバッグ
+debug.tooltip=Krb5LoginModule の標準出力へのデバッグロギングの有効/無効を設定します。
+allow-password-authentication=パスワード認証を許可
+allow-password-authentication.tooltip=Kerberos データベースに対するユーザー名/パスワード認証の有効/無効を設定します。
+edit-mode=編集モード
+edit-mode.tooltip=READ_ONLY は、パスワード更新は許可されずユーザーは常に Kerberos のパスワードで認証することを意味します。UNSYNCED は、ユーザーは Keycloak データベース内の自分のパスワードを変更可能であり、Kerberos のパスワードの代わりに使用されることを意味します。
+ldap.edit-mode.tooltip=READ_ONLY は、読み取り専用の LDAP ストアです。WRITABLE は、データがオンデマンドで LDAP に書き戻しされることを意味します。UNSYNCEDは、ユーザーデータはインポートされますが、LDAP に書き戻しはされないことを意味します。
+update-profile-first-login=初回ログイン時にプロフィールを更新
+update-profile-first-login.tooltip=初回ログイン時のプロフィール更新の有効/無効を設定します。
+sync-registrations=登録の同期
+ldap.sync-registrations.tooltip=LDAP ストア内に新規作成ユーザーを作成すべきかどうかを設定します。どのプロバイダーが新しいユーザーの同期先に選択されるかは、優先度が影響します。
+vendor=ベンダー
+ldap.vendor.tooltip=LDAP ベンダー (プロバイダー)
+username-ldap-attribute=ユーザー名の LDAP 属性
+ldap-attribute-name-for-username=ユーザー名の LDAP 属性名
+username-ldap-attribute.tooltip=Keycloak ユーザー名にマッピングされる LDAP 属性名を設定します。多くの LDAP サーバーベンダーでは 「uid」 となります。Active Directory では 「sAMAccountName」 または 「cn」 となります。LDAP から Keycloak にインポートするすべての LDAP ユーザーのレコードで、属性は入力されているはずです。
+rdn-ldap-attribute=RDN LDAP 属性
+ldap-attribute-name-for-user-rdn=ユーザー RDN の LDAP 属性名
+rdn-ldap-attribute.tooltip=一般的なユーザー DN の RDN (top 属性) として使用される LDAP 属性名を設定します。通常は、ユーザー名の LDAP 属性 と同じですが、必須ではありません。例えば Active Directory では、ユーザー名が 「sAMAccountName」 だと RDN 属性として 「cn」 を使用するのが一般的です。
+uuid-ldap-attribute=UUID LDAP 属性
+ldap-attribute-name-for-uuid=UUID の LDAP 属性名
+uuid-ldap-attribute.tooltip=LDAP 内でオブジェクトのユニークなオブジェクト識別子 (UUID) として使用される LDAP 属性名を設定します。多くの LDAP サーバーベンダーでは 「entryUUID」 となりますが、異なる場合もあります。例えば Active Directory では、 「objectGUID」 となります。お使いの LDAP サーバーが UUID をサポートしていない場合は、ツリー内の LDAP ユーザーの中でユニークとなる他の属性を使用することができます。例えば、 「uid」 や 「entryDN」 です。
+user-object-classes=ユーザーオブジェクトクラス
+ldap-user-object-classes.placeholder=LDAP のユーザーオブジェクトクラス (カンマ区切り)
+
+ldap-connection-url=LDAP 接続 URL
+ldap-users-dn=LDAP ユーザー DN
+ldap-bind-dn=LDAP Bind DN
+ldap-bind-credentials=LDAP Bind のクレデンシャル
+ldap-filter=LDAP フィルター
+ldap.user-object-classes.tooltip=LDAP ユーザー用の すべての LDAP オブジェクトクラスをカンマ区切りで設定します。例: 「inetOrgPerson, organizationalPerson」 。新規作成された Keycloak ユーザーは、これらすべてのオブジェクトクラスを使用して LDAP に書き込まれます。また、既存の LDAP ユーザーのレコードは、これらすべてのオブジェクトクラスを含む場合だけ発見されます。
+
+connection-url=接続 URL
+ldap.connection-url.tooltip=お使いの LDAP サーバーへの接続 URL
+test-connection=接続テスト
+users-dn=ユーザー DN
+ldap.users-dn.tooltip=ユーザーがいる LDAP ツリーの完全 DN を設定します。この DN は LDAP ユーザーの親になります。例えば、典型的なユーザーは 「uid=john,ou=users,dc=example,dc=com」 「ou=users,dc=example,dc=com」 のような DN となりますが、この場合は 「ou=users,dc=example,dc=com」 となります。
+authentication-type=認証タイプ
+ldap.authentication-type.tooltip=LDAP 認証タイプを設定します。今のところ、 「none」 (Anonymous LDAP 認証) または 「simple」 (クレデンシャルによる Bind + パスワード認証による Bind) メカニズムが用意されています。
+bind-dn=Bind DN
+ldap.bind-dn.tooltip=Keycloak が LDAP サーバーにアクセスするために使用する LDAP 管理者の DN を設定します。
+bind-credential=Bind のクレデンシャル
+ldap.bind-credential.tooltip=LDAP 管理者のパスワードを設定します。
+test-authentication=認証テスト
+custom-user-ldap-filter=カスタムユーザー LDAP フィルター
+ldap.custom-user-ldap-filter.tooltip=ユーザー検索のフィルタリングを行う LDAP フィルターを設定します。追加のフィルターが必要ない場合は空のままにしてください。設定は、 「(」 から始まり 「)」 で終わることを確認してください。
+search-scope=検索スコープ
+ldap.search-scope.tooltip=One Level では、ユーザー DN で指定された DN 内のユーザーのみを検索します。subtree では、サブツリー全体を検索します。より詳細については LDAP のドキュメントを参照してください。
+use-truststore-spi=トラストストア SPI を使用
+ldap.use-truststore-spi.tooltip=LDAP 接続で、keycloak-server.json で設定されたトラストストアの トラストストア SPI を使用するかどうかを指定します。 「Always」 は常に使用することを意味します。 「Never」 は使用しないことを意味します。 「Only for ldaps」 は、接続 URL が ldaps の場合に使用することを意味します。keycloak-server.json で設定されていない場合でも、デフォルトの Java CA 証明書 (cacerts) や 「javax.net.ssl.trustStore」 プロパティで指定された証明書が使用される点に注意してください。
+connection-pooling=接続プーリング
+ldap.connection-pooling.tooltip=Keycloak は LDAP サーバーへのアクセスで接続プールを使用するかどうかを設定します。
+ldap.pagination.tooltip=LDAP サーバーはページネーションをサポートするかどうかを設定します。
+kerberos-integration=Kerberos と統合
+allow-kerberos-authentication=Kerberos 認証を許可
+ldap.allow-kerberos-authentication.tooltip=SPNEGO/Kerberos のトークンを持つユーザーの HTTP 認証を有効/無効にします。認証されたユーザーに関するデータはこの LDAP サーバーよりプロビジョニングされます。
+use-kerberos-for-password-authentication=パスワード認証に Kerberos を使用
+ldap.use-kerberos-for-password-authentication.tooltip=LDAP サーバーに対してディレクトリサービスの API で認証する代わりに、Kerberos に対して ユーザー名/パスワード認証する Kerberos ログインモジュールを使用します。
+batch-size=バッチサイズ
+ldap.batch-size.tooltip=1トランザクションで LDAP から Keycloak にインポートされる LDAP ユーザー数を設定します。
+ldap.periodic-full-sync.tooltip=Keycloak への LDAP ユーザーの定期的なフル同期を有効/無効にします。
+ldap.periodic-changed-users-sync.tooltip=Keycloak への 変更または新規作成された LDAP ユーザーの定期的な同期を有効/無効にします。
+ldap.changed-users-sync-period.tooltip=変更または新規作成された LDAP ユーザーの同期周期を秒で設定します。
+user-federation-mappers=ユーザーフェデレーションのマッパー
+create-user-federation-mapper=ユーザーフェデレーション マッパーの作成
+add-user-federation-mapper=ユーザーフェデレーション マッパーの追加
+provider-name=プロバイダー名
+no-user-federation-providers-configured=設定されているユーザーフェデレーション プロバイダーはありません
+no-user-storage-providers-configured=設定されているユーザーストレージ プロバイダーはありません
+add-identity-provider=アイデンティティ プロバイダーの登録
+add-identity-provider-link=アイデンティティ プロバイダーのリンク登録
+identity-provider=アイデンティティ プロバイダー
+identity-provider-user-id=アイデンティティ プロバイダーのユーザー ID
+identity-provider-user-id.tooltip=アイデンティティ プロバイダー側のユーザーのユニーク ID です。
+identity-provider-username=アイデンティティ プロバイダーのユーザー名
+identity-provider-username.tooltip=アイデンティティ プロバイダー側のユーザー名です。
+pagination=ページネーション
+
+browser-flow=ブラウザーフロー
+browser-flow.tooltip=ブラウザー認証で使用したいフローを選択してください。
+registration-flow=登録フロー
+registration-flow.tooltip=登録で使用したいフローを選択してください。
+direct-grant-flow=ダイレクトグラントフロー
+direct-grant-flow.tooltip=ダイレクトグラント認証で使用したいフローを選択してください。
+reset-credentials=クレデンシャルのリセット
+reset-credentials.tooltip=ユーザーがクレデンシャルを忘れた際に使用したいフローを選択してください。
+client-authentication=クライアント認証
+client-authentication.tooltip=クライアント認証で使用したいフローを選択してください。
+new=新規作成
+copy=コピー
+add-execution=Execution を追加
+add-flow=フローを追加
+auth-type=認証タイプ
+requirement=必要条件
+config=設定
+no-executions-available=使用可能な Execution がありません
+authentication-flows=認証フロー
+create-authenticator-config=認証設定の作成
+authenticator.alias.tooltip=この設定の名前を設定します。
+otp-type=OTP タイプ
+time-based=タイムベース
+counter-based=カウンターベース
+otp-type.tooltip=TOTP はタイムベースのワンタイムパスワードです。 「hotp」 は、サーバーでハッシュに対してカウンターを保持するカウンターベースのワンタイムパスワードです。
+otp-hash-algorithm=OTP ハッシュアルゴリズム
+otp-hash-algorithm.tooltip=OTP を生成するのにどのハッシュアルゴリズムを使用するか設定します。
+number-of-digits=桁数
+otp.number-of-digits.tooltip=OTP の桁数を設定します。
+look-ahead-window=先読みウィンドウ
+otp.look-ahead-window.tooltip=トークンジェネレーターとサーバーが時刻同期またはカウンター同期していないことを考慮してどれくらい先読みを行うか設定します。
+initial-counter=初期カウンター
+otp.initial-counter.tooltip=初期カウンターの値は何とするか設定します。
+otp-token-period=OTP トークンの期間
+otp-token-period.tooltip=OTP トークンは何秒有効とするか設定します。デフォルトは30秒です。
+table-of-password-policies=パスワードポリシーの一覧表
+add-policy.placeholder=ポリシーを追加...
+policy-type=ポリシーのタイプ
+policy-value=ポリシーの値
+admin-events=管理イベント
+admin-events.tooltip=保存されたレルムの管理イベントを表示します。管理イベントは、アカウント管理に関連したイベント、例えばレルムの作成などです。イベントの保存を有効にするには設定へ移動してください。
+login-events=ログインイベント
+filter=フィルター
+update=更新
+reset=リセット
+operation-types=操作タイプ
+resource-types=リソースタイプ
+select-operations.placeholder=操作を選択...
+select-resource-types.placeholder=リソースタイプを選択...
+resource-path=リソースパス
+resource-path.tooltip=リソースパスでフィルターします。ワイルドカード 「*」 はパスの単一部分と一致し、 「**」 は複数部分と一致します。例えば、 「realms/*/clients/asbc」 はすべてのレルム内の ID asbc を持つクライアントとマッチし、 「realms/master/**」 は master レルム内のすべてにマッチします。
+date-(from)=日付 (From)
+date-(to)=日付 (To)
+authentication-details=認証の詳細
+ip-address=IP アドレス
+time=日時
+operation-type=操作タイプ
+resource-type=リソースタイプ
+auth=認証
+representation=Representation
+register=登録
+required-action=Required アクション
+default-action=デフォルトアクション
+auth.default-action.tooltip=有効の場合は、新規ユーザーにはこの Required アクションがアサインされます。
+no-required-actions-configured=設定された Required アクションはありません
+defaults-to-id=ID がデフォルトになります
+flows=フロー
+bindings=バインディング
+required-actions=Required アクション
+password-policy=パスワードポリシー
+otp-policy=OTP ポリシー
+user-groups=ユーザーグループ
+default-groups=デフォルトグループ
+groups.default-groups.tooltip=新規ユーザーが自動的に参加するグループのセットを設定します。
+cut=カット
+paste=ペースト
+
+create-group=グループの作成
+create-authenticator-execution=認証 Execution の作成
+create-form-action-execution=フォームアクション Execution の作成
+create-top-level-form=トップレベルフォームの作成
+flow.alias.tooltip=フローの表示名を指定します。
+top-level-flow-type=トップレベルフロータイプ
+flow.generic=generic
+flow.client=client
+top-level-flow-type.tooltip=どの種類のトップレベルフローを作成しますか? 「client」 タイプは、クライアント (アプリケーション) の認証で使用します。 「generic」 はユーザーと他のすべてで使用します。
+create-execution-flow=Execution フローの作成
+flow-type=フロータイプ
+flow.form.type=form
+flow.generic.type=generic
+flow-type.tooltip=どの種類のフォームかを設定します。
+form-provider=フォームプロバイダー
+default-groups.tooltip=新規作成または登録されたユーザーは自動的にこれらのグループに追加されます。
+select-a-type.placeholder=タイプを選択してください
+available-groups=使用可能なグループ
+available-groups.tooltip=デフォルトとして追加したいグループを選択してください。
+value=値
+table-of-group-members=グループメンバーの一覧表
+last-name=姓
+first-name=名
+email=Eメール
+toggle-navigation=ナビゲーションの切り替え
+manage-account=アカウントの管理
+sign-out=サインアウト
+server-info=サーバー情報
+resource-not-found=リソースが<strong>見つかりません</strong>...
+resource-not-found.instruction=お探しのリソースが見つかりませんでした。入力された URL が正しいかご確認ください。
+go-to-the-home-page=ホームページへ移動 &raquo;
+page-not-found=ページが<strong>見つかりません</strong>...
+page-not-found.instruction=お探しのページが見つかりませんでした。入力された URL が正しいかご確認ください。
+events.tooltip=保存されたレルムのイベントを表示します。イベントは、ユーザーアカウントに関連したイベント、例えばログインなどです。イベントの保存を有効にするには設定へ移動してください。
+select-event-types.placeholder=イベントタイプを選択...
+events-config.tooltip=ユーザーと管理イベントの保存を有効にする設定オプションを表示します。
+select-an-action.placeholder=アクションを選択...
+event-listeners.tooltip=どのリスナーがレルムのイベントを受け取るか設定します。
+login.save-events.tooltip=有効の場合は、ログインイベントがデータベースに保存され、管理コンソールとアカウント管理で使用することができます。
+clear-events.tooltip=データベース内のすべてのイベントを削除します。
+events.expiration.tooltip=イベントの有効期限を設定します。期限切れのイベントはデータベースから定期的に削除されます。
+admin-events-settings=管理イベントの設定
+save-events=イベントの保存
+admin.save-events.tooltip=有効の場合は、管理イベントがデータベースに保存され、管理コンソールで使用可能になります。
+saved-types.tooltip=どのイベントタイプが保存されるかを設定します。
+include-representation=Representation を含める
+include-representation.tooltip=作成または更新リクエストの JSON Representation を含めるかどうかを設定します。
+clear-admin-events.tooltip=データベース内のすべての管理イベントを削除します。
+server-version=サーバーのバージョン
+info=情報
+providers=プロバイダー
+server-time=サーバーの時刻
+server-uptime=サーバーの稼働時間
+memory=メモリー
+total-memory=メモリーの総容量
+free-memory=空きメモリー
+used-memory=使用メモリー
+system=システム
+current-working-directory=現在の作業ディレクトリ
+java-version=Java バージョン
+java-vendor=Java ベンダー
+java-runtime=Java ランタイム
+java-vm=Java VM
+java-vm-version=Java VM バージョン
+java-home=Java ホーム
+user-name=ユーザー名
+user-timezone=ユーザータイムゾーン
+user-locale=ユーザーロケール
+system-encoding=システムエンコーディング
+operating-system=オペレーションシステム
+os-architecture=OS アーキテクチャ
+spi=SPI
+granted-roles=許可されたロール
+granted-protocol-mappers=許可されたプロトコルマッパー
+additional-grants=追加の許可
+revoke=取り消し
+new-password=新しいパスワード
+password-confirmation=新しいパスワード (確認)
+reset-password=パスワードをリセット
+credentials.temporary.tooltip=有効の場合は、ユーザーは次のログイン時にパスワードの変更が必要となります。
+remove-totp=TOTP の削除
+credentials.remove-totp.tooltip=ユーザーのワンタイムパスワードジェネレーターを削除します。
+reset-actions=リセットアクション
+credentials.reset-actions.tooltip=ユーザーにリセットアクションEメールを送信する際に実行するアクションを設定します。 「Verify email」 は、メールアドレスの確認のためにユーザーにEメールを送信します。 「Update profile」 は、新しい個人情報の入力を必要とします。 「Update password」 は、新しいパスワードの入力を必要とします。 「Configure TOTP」 は、モバイルのパスワードジェネレーターのセットアップを必要とします。
+reset-actions-email=リセットアクションEメール
+send-email=Eメールを送信
+credentials.reset-actions-email.tooltip=リンクを記載したEメールをユーザーに送信します。リンクをクリックすることで、ユーザーはリセットアクションを実行できます。ユーザーはリセットの前にログインする必要はありません。例えば、 「Update Password」 アクションを設定してこのボタンをクリックすると、ユーザーはログインなしにパスワードの変更が可能になります。
+add-user=ユーザーの追加
+created-at=作成日
+user-enabled=ユーザーの有効
+user-enabled.tooltip=無効ユーザーはログインすることができません。
+user-temporarily-locked=ユーザーの一時的なロック
+user-temporarily-locked.tooltip=ユーザーは何度もログインに失敗してロックされている可能性があります。
+unlock-user=ユーザーをアンロック
+federation-link=フェデレーション リンク
+email-verified=確認済みのEメール
+email-verified.tooltip=ユーザーのEメールは確認済みかどうか設定します。
+required-user-actions=必要なユーザーアクション
+required-user-actions.tooltip=ユーザーがログイン時に必要となるアクションを設定します。 「Verify email」 は、メールアドレスの確認のためにユーザーにEメールを送信します。 「Update profile」 は、新しい個人情報の入力を必要とします。 「Update password」 は、新しいパスワードの入力を必要とします。 「Configure TOTP」 は、モバイルのパスワードジェネレーターのセットアップを必要とします。
+locale=ロケール
+select-one.placeholder=1つ選択...
+impersonate=代理ログイン
+impersonate-user=ユーザーの代理
+impersonate-user.tooltip=このユーザーとしてログインします。同じレルム内のユーザーの場合は、このユーザーでログインする前に、現在のログインセッションがログアウトされます。
+identity-provider-alias=アイデンティティ プロバイダーのエイリアス
+provider-user-id=プロバイダーのユーザー ID
+provider-username=プロバイダーのユーザー名
+no-identity-provider-links-available=使用可能なアイデンティティ プロバイダーのリンクはありません
+group-membership=グループメンバーシップ
+leave=外す
+group-membership.tooltip=メンバーであるグループです。グループから外すには、リストのグループを選択して 「外す」 ボタンをクリックしてください。
+membership.available-groups.tooltip=ユーザーが参加可能なグループです。グループを選択して 「参加」 ボタンをクリックしてください。
+table-of-realm-users=レルムユーザーの一覧表
+view-all-users=すべてのユーザーを参照
+unlock-users=ユーザーのアンロック
+no-users-available=使用可能なユーザーはおりません
+users.instruction=検索を入力するか、 「すべてのユーザーを参照」 をクリックしてください
+consents=同意
+started=開始
+logout-all-sessions=すべてのセッションをログアウト
+logout=ログアウト
+new-name=新しい名前
+ok=OK
+attributes=属性
+role-mappings=ロールマッピング
+members=メンバー
+details=詳細
+identity-provider-links=アイデンティティ プロバイダーのリンク
+register-required-action=Required アクションの登録
+gender=性別
+address=住所
+phone=電話番号
+profile-url=プロフィール URL
+picture-url=画像 URL
+website=Web サイト
+import-keys-and-cert=鍵と証明書をインポート
+import-keys-and-cert.tooltip=クライアントの鍵ペアと証明書をアップロードします。
+upload-keys=鍵をアップロード
+download-keys-and-cert=鍵と証明書をダウンロード
+no-value-assigned.placeholder=アサイン済みの値はありません
+remove=削除
+no-group-members=グループメンバーはおりません
+temporary=一時的
+join=参加
+event-type=イベントタイプ
+events-config=イベント設定
+event-listeners=イベントリスナー
+login-events-settings=ログインイベントの設定
+clear-events=イベントのクリア
+saved-types=保存タイプ
+clear-admin-events=管理イベントのクリア
+clear-changes=変更をクリア
+error=エラー
+
+# Authz
+# Authz Common
+authz-authorization=認可
+authz-owner=オーナー
+authz-uri=URI
+authz-scopes=スコープ
+authz-resource=リソース
+authz-resource-type=リソースタイプ
+authz-resources=リソース
+authz-scope=スコープ
+authz-authz-scopes=認可スコープ
+authz-policies=ポリシー
+authz-permissions=アクセス権
+authz-evaluate=評価
+authz-icon-uri=アイコン URI
+authz-icon-uri.tooltip=アイコンを指す URI を設定します。
+authz-select-scope=スコープを選択
+authz-select-resource=リソースを選択
+authz-associated-policies=関連ポリシー
+authz-any-resource=任意のリソース
+authz-any-scope=任意のスコープ
+authz-any-role=任意のロール
+authz-policy-evaluation=ポリシー評価
+authz-select-client=クライアントを選択
+authz-select-user=ユーザーを選択
+authz-entitlements=エンタイトルメント
+authz-no-resources=リソースはありません
+authz-result=結果
+authz-authorization-services-enabled=認可の有効
+authz-authorization-services-enabled.tooltip=きめ細かい認可のサポートを有効/無効にします。
+authz-required=必須
+
+# Authz Settings
+authz-import-config.tooltip=リソースサーバーの認可設定を含む JSON ファイルをインポートします。
+
+authz-policy-enforcement-mode=ポリシー施行モード
+authz-policy-enforcement-mode.tooltip=ポリシー施行モードは、認可リクエストを評価する際に適用される方法を決定します。 「Enforcing」 は、与えられたリソースに関連するポリシーが存在しない場合でも、リクエストはデフォルトで拒否されることを意味します。 「Permissive」 は、与えられたリソースに関連するポリシーが存在しない場合でも、リクエストは許可されることを意味します。 「Disabled」 は、完全にポリシーの評価を無効にし、任意のリソースへのアクセスを許可します。
+authz-policy-enforcement-mode-enforcing=Enforcing
+authz-policy-enforcement-mode-permissive=Permissive
+authz-policy-enforcement-mode-disabled=Disabled
+
+authz-remote-resource-management=リモートリソース管理
+authz-remote-resource-management.tooltip=リソースは、リソースサーバーによりリモートで管理すべきかどうかを設定します。 オフの場合は、リソースはこの管理コンソールだけで管理されます。
+
+authz-export-settings=エクスポート設定
+authz-export-settings.tooltip=このリソースサーバーのすべての認可設定をエクスポートしダウンロードします。
+
+# Authz Resource List
+authz-no-resources-available=使用可能なリソースはありません。
+authz-no-scopes-assigned=アサイン済みのスコープはありません。
+authz-no-type-defined=定義されたタイプはありません。
+authz-no-permission-assigned=アサイン済みのアクセス権はありません。
+authz-no-policy-assigned=アサイン済みのポリシーはありません。
+authz-create-permission=アクセス権を作成
+
+# Authz Resource Detail
+authz-add-resource=リソースの追加
+authz-resource-name.tooltip=このリソースのユニークな名前を設定します。名前はリソースの一意な識別に使用され、特定のリソースを照会する際に使用することができます。
+authz-resource-owner.tooltip=このリソースのオーナーです。
+authz-resource-type.tooltip=このリソースのタイプを設定します。異なるリソースインスタンスを同じタイプにグルーピングすることができます。
+authz-resource-uri.tooltip=このリソースを一意に識別する URI を設定します。
+authz-resource-scopes.tooltip=このリソースに関連付けるスコープを設定します。
+
+# Authz Scope List
+authz-add-scope=スコープの追加
+authz-no-scopes-available=使用可能なスコープはありません。
+
+# Authz Scope Detail
+authz-scope-name.tooltip=このスコープのユニークな名前を設定します。名前はスコープの一意な識別に使用され、特定のスコープを照会する際に使用することができます。
+
+# Authz Policy List
+authz-all-types=すべてのタイプ
+authz-create-policy=ポリシーを作成
+authz-no-policies-available=使用可能なポリシーはありません。
+
+# Authz Policy Detail
+authz-policy-name.tooltip=このポリシーの名前を設定します。
+authz-policy-description.tooltip=このポリシーの説明を設定します。
+authz-policy-logic=ロジック
+authz-policy-logic-positive=Positive
+authz-policy-logic-negative=Negative
+authz-policy-logic.tooltip=ロジックは、ポリシーの判定方法を決定します。 「Positive」 の場合は、このポリシーの評価中に得られた結果 (許可または拒否) が判定の実行に使用されます。 「Negative」 の場合は、結果は反転されます。言い換えれば、許可は拒否とその反対になります。
+authz-policy-apply-policy=ポリシーの適用
+authz-policy-apply-policy.tooltip=このポリシーやアクセス権で定義されたスコープに適用するすべてのポリシーを設定します。
+authz-policy-decision-strategy=判定戦略
+authz-policy-decision-strategy.tooltip=判定戦略は、ポリシーの評価方法と最終的な判定方法を決定します。 「Affirmative」 は、全体の判定が positive となるためには、少なくとも1つのポリシーが positive と評価する必要がある、ということを意味します。 「Unanimous」 は、全体の判定が positive となるためには、すべてのポリシーが positive と評価する必要がある、ということを意味します。 「Consensus」 は、positive の数が nagative の数より多くなければならないことを意味します。positive と negative の数が同じ場合は、最終的な判定は negative になります。
+authz-policy-decision-strategy-affirmative=Affirmative
+authz-policy-decision-strategy-unanimous=Unanimous
+authz-policy-decision-strategy-consensus=Consensus
+authz-select-a-policy=ポリシーを選択
+
+# Authz Role Policy Detail
+authz-add-role-policy=ロールポリシーの追加
+authz-no-roles-assigned=アサイン済みのロールはありません。
+authz-policy-role-realm-roles.tooltip=このポリシーで許可されるレルムロールを指定してください。
+authz-policy-role-clients.tooltip=このポリシーに適用されるクライアントロールをフィルタリングするために、クライアントを選択してください。
+authz-policy-role-client-roles.tooltip=このポリシーで許可されるクライアントロールを指定してください。
+
+# Authz User Policy Detail
+authz-add-user-policy=ユーザーポリシーの追加
+authz-no-users-assigned=アサイン済みのユーザーはおりません。
+authz-policy-user-users.tooltip=どのユーザーがこのポリシーで許可されるか指定してください。
+
+# Authz Time Policy Detail
+authz-add-time-policy=タイムポリシーの追加
+authz-policy-time-not-before.tooltip=ポリシーを許可しない日時を定義します。現在日時がこの値より後か、等しい場合にのみ許可されます。
+authz-policy-time-not-on-after=この日時より後
+authz-policy-time-not-on-after.tooltip=ポリシーを許可しない日時を定義します。現在日時がこの値より前か、等しい場合にのみ許可されます。
+
+# Authz Drools Policy Detail
+authz-add-drools-policy=Drools ポリシーの追加
+authz-policy-drools-maven-artifact-resolve=解決
+authz-policy-drools-maven-artifact=ポリシー Maven アーティファクト
+authz-policy-drools-maven-artifact.tooltip=ルールの読み込む先となるアーティファクトを示す Maven GAV を設定します。GAV を提供し 「解決」 をクリックすることで、 「モジュール」 と 「セッション」 フィールドを読み込みます。
+authz-policy-drools-module=モジュール
+authz-policy-drools-module.tooltip=このポリシーで使用されるモジュールです。ルールの読み込み先から特定のセッションを選択するにはモジュールを提供する必要があります。
+authz-policy-drools-session=セッション
+authz-policy-drools-session.tooltip=このポリシーで使用されるセッションです。セッションは、ポリシーを処理する際に評価するすべてのルールを提供します。
+authz-policy-drools-update-period=更新周期
+authz-policy-drools-update-period.tooltip=アーティファクトの更新をスキャンする間隔を指定します。
+
+# Authz JS Policy Detail
+authz-add-js-policy=JavaScript ポリシーの追加
+authz-policy-js-code=コード
+authz-policy-js-code.tooltip=このポリシーの条件を提供する JavaScript コードを設定します。
+
+
+# Authz Aggregated Policy Detail
+authz-aggregated=集約
+authz-add-aggregated-policy=集約ポリシーの追加
+
+# Authz Permission List
+authz-no-permissions-available=使用可能なアクセス権はありません。
+
+# Authz Permission Detail
+authz-permission-name.tooltip=このアクセス権の名前を設定します。
+authz-permission-description.tooltip=このアクセス権の説明を設定します。
+
+# Authz Resource Permission Detail
+authz-add-resource-permission=リソースアクセス権の追加
+authz-permission-resource-apply-to-resource-type=リソースタイプに適用
+authz-permission-resource-apply-to-resource-type.tooltip=このアクセス権が、特定タイプの全リソースに適用されるかどうかを指定します。この場合、アクセス権は特定リソースタイプの全インスタンスに対して評価されます。
+authz-permission-resource-resource.tooltip=このアクセス権が適用されるリソースインスタンスを指定します。
+authz-permission-resource-type.tooltip=このアクセス権が適用されるリソースタイプを指定します。
+
+# Authz Scope Permission Detail
+authz-add-scope-permission=スコープアクセス権の追加
+authz-permission-scope-resource.tooltip=選択されたリソースに関連するスコープに制限します。選択されていない場合は、すべてのスコープが使用可能になります。
+authz-permission-scope-scope.tooltip=このアクセス権は1つまたは複数のスコープに適用されるように指定してください。
+
+# Authz Evaluation
+authz-evaluation-identity-information=アイデンティティ情報
+authz-evaluation-identity-information.tooltip=ポリシーの評価の際に使用されるアイデンティティ情報の設定オプションです。
+authz-evaluation-client.tooltip=認可リクエストを作成するクライアントを選択してください。提供されない場合は、認可リクエストは今いるページのクライアントで行われることになります。
+authz-evaluation-user.tooltip=アクセス権を照会するために使用するユーザーのアイデンティティを選択してください。
+authz-evaluation-role.tooltip=選択されたユーザーに関連付けたいロールを選択してください。
+authz-evaluation-new=新規に評価
+authz-evaluation-re-evaluate=再評価
+authz-evaluation-previous=前の評価
+authz-evaluation-contextual-info=コンテキスト情報
+authz-evaluation-contextual-info.tooltip=ポリシーの評価の際に使用されるコンテキスト情報の設定オプションです。
+authz-evaluation-contextual-attributes=コンテキスト属性
+authz-evaluation-contextual-attributes.tooltip=実行環境や実行コンテキストによって提供される任意の属性を設定します。
+authz-evaluation-permissions.tooltip=ポリシーが適用されるようにアクセス権を設定するオプションです。
+authz-evaluation-evaluate=評価
+authz-evaluation-any-resource-with-scopes=スコープを持つ任意のリソース
+authz-evaluation-no-result=認可リクエストから結果を得ることができませんでした。提供されたリソースまたはスコープが、ポリシーと関連付けられているかどうかを確認してください。
+authz-evaluation-no-policies-resource=このリソースのポリシーが見つかりませんでした。
+authz-evaluation-result.tooltip=このアクセス権のリクエストの全体的な結果です。
+authz-evaluation-scopes.tooltip=許可されたスコープリストです。
+authz-evaluation-policies.tooltip=どのポリシーが評価され判定されたか詳細を表示しています。
+authz-evaluation-authorization-data=レスポンス
+authz-evaluation-authorization-data.tooltip=認可リクエストの処理の結果として送信された認可データのトークンを表示します。これは、許可を求めたクライアントに対して Keycloak が発行する基本的なものです。現在の認可リクエストで付与されたアクセス権については 「authorization」 クレームを確認してください。
+authz-show-authorization-data=認可データを表示
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
new file mode 100644
index 0000000..574eb91
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_no.properties
@@ -0,0 +1,1118 @@
+consoleTitle=Keycloak administrasjonskonsoll
+
+# Common messages
+enabled=Aktivert
+name=Navn
+displayName=Vis navn
+displayNameHtml=HTML vis navn
+save=Lagre
+cancel=Avbryt
+onText=P\u00C5
+offText=AV
+client=Klient
+clients=Klienter
+clear=T\u00F8m
+selectOne=Velg en...
+
+true=True
+false=False
+
+endpoints=Endepunkter
+
+# Realm settings
+realm-detail.enabled.tooltip=Brukere og klienter har kun tilgang til et sikkerhetsdomene hvis det er aktivert
+realm-detail.oidc-endpoints.tooltip=Viser konfigurasjonen av endepunkter for OpenID Connect
+registrationAllowed=Registrering av bruker
+registrationAllowed.tooltip=Aktiver/deaktiver registreringssiden. En lenke for registrering vil v\u00E6re synlig p\u00E5 innloggingssiden.
+registrationEmailAsUsername=E-postadresse som brukernavn
+registrationEmailAsUsername.tooltip=Dersom registreringssiden er aktivert, vil feltet for brukernavn v\u00E6re skjult fra registreringsskjema og e-postadresse vil bli brukt som brukernavn for nye brukere.
+editUsernameAllowed=Rediger brukernavn
+editUsernameAllowed.tooltip=Dersom aktivert, er feltet for brukernavn redigerbart, ellers kun lesbart.
+resetPasswordAllowed=Glemt passord
+resetPasswordAllowed.tooltip=Vis en lenke p\u00E5 innloggingssiden som brukere kan klikke p\u00E5 om de har glemt sine innloggingsdetaljer.
+rememberMe=Husk meg
+rememberMe.tooltip=Vis en avkryssingsboks p\u00E5 innloggingssiden som lar brukere forbli innlogget mellom omstart av nettleser og inntil sesjonen utl\u00F8per.
+verifyEmail=Bekreft e-postadresse
+verifyEmail.tooltip=Krev at bruker verifiserer sin e-postadresse f\u00F8rste gang de logger inn.
+sslRequired=Krev SSL
+sslRequired.option.all=Alle foresp\u00F8rsler
+sslRequired.option.external=Eksterne foresp\u00F8rsler
+sslRequired.option.none=Ingen
+sslRequired.tooltip=Kreves HTTPS? 'Ingen' betyr at HTTPS ikke kreves for noen klienters IP-adresse. 'Ekstern foresp\u00F8rsel' betyr at localhost og private IP-adresser kan f\u00E5 tilgang uten HTTPS. 'Alle foresp\u00F8rsler' betyr at HTTPS kreves for alle IP-adresser.
+publicKey=Offentlig n\u00F8kkel
+privateKey=Privat n\u00F8kkel
+gen-new-keys=Generer nye n\u00F8kler
+certificate=Sertifikat
+host=Vert
+smtp-host=SMTP Vert
+port=Port
+smtp-port=SMTP Port (standard er 25)
+from=Fra
+sender-email-addr=Senders e-postadresse
+enable-ssl=Aktiver SSL
+enable-start-tls=Aktiver StartTLS
+enable-auth=Aktiver autentisering
+username=Brukernavn
+login-username=Innloggingsbrukernavn
+password=Passord
+login-password=Innloggingspassord
+login-theme=Innloggingstema
+login-theme.tooltip=Velg tema for sidene: innlogging, TOTP, rettigheter, registrering, glemt passord.
+account-theme=Kontotema
+account-theme.tooltip=Velg tema for brukerkontoadministrasjonssider.
+admin-console-theme=Administrasjonskonsolltema
+select-theme-admin-console=Velg et tema for administrasjonskonsollen.
+email-theme=E-posttema
+select-theme-email=Velg tema for e-post sendt av server.
+i18n-enabled=Internasjonalisering aktivert
+supported-locales=St\u00F8ttede lokaliteter
+supported-locales.placeholder=Skriv inn en lokalitet og klikk enter
+default-locale=Standard lokalitet
+realm-cache-clear=Cache for sikkerhetsdomenet
+realm-cache-clear.tooltip=T\u00F8m sikkerhetsdomenecache (Dette vil fjerne oppf\u00F8ringer for alle sikkerhetsdomener)
+user-cache-clear=Brukercache
+user-cache-clear.tooltip=T\u00F8m brukercache (Dette vil fjerne oppf\u00F8ringer for alle sikkerhetsdomener)
+revoke-refresh-token=Fjern refresh token
+revoke-refresh-token.tooltip=Hvis aktivert kan refresh token kun bli brukt en gang. Ellers vil refresh tokens kunne bli brukt flere ganger.
+sso-session-idle=Inaktiv SSO sesjon
+seconds=Sekunder
+minutes=Minutter
+hours=Timer
+days=Dager
+sso-session-max=Maksimum SSO sesjon
+sso-session-idle.tooltip=Tiden en sesjon er tillatt \u00E5 v\u00E6re inaktiv f\u00F8r den utl\u00F8per. Tokens og nettlesersesjoner vil bli ugyldig n\u00E5r en sesjon utl\u00F8per.
+sso-session-max.tooltip=Maksimum tid f\u00F8r en sesjon utl\u00F8per. Tokens og nettlesersesjoner vil bli ugyldig n\u00E5r en sesjon utl\u00F8per.
+offline-session-idle=Inaktiv sesjon i frakoblet modus
+offline-session-idle.tooltip=Tiden en sesjon i frakoblet modus er tillatt \u00E5 v\u00E6re inaktiv f\u00F8r den utl\u00F8per. Du m\u00E5 bruke tokens for frakoblet modus for \u00E5 oppdatere sesjonen minst en gang i denne perioden, ellers vil sesjonen utl\u00F8pe.
+access-token-lifespan=Levetid for access token
+access-token-lifespan.tooltip= Maksimum tid f\u00F8r et access token utl\u00F8per. Det anbefales at denne verdien er kort i forhold til SSO timeout.
+access-token-lifespan-for-implicit-flow=Access token-levetid for implicit flow
+access-token-lifespan-for-implicit-flow.tooltip=Maksimum tid f\u00F8r et access token utstedt under OpenID Connect implicit flow utl\u00F8per. Det anbefales at denne er kortere enn SSO timeout. Det er ingen mulighet til \u00E5 oppdatere tokenet i l\u00F8pet av en implicit flow, derfor er det satt en separat timeout som er forskjellig fra 'Levetid for Access Token'.
+client-login-timeout=Timeout av klientinnlogging
+client-login-timeout.tooltip=Maksimum tid en klient har for \u00E5 fullf\u00F8re access token protokollen. Dette burde normalt v\u00E6re 1 minutt.
+login-timeout=Timeout for innlogging
+login-timeout.tooltip=Maksimum tid en bruker har til \u00E5 fullf\u00F8re en innlogging. Det anbefales at denne er relativt lang. 30 minutter eller mer.
+login-action-timeout=Timeout for innloggingshandling.
+login-action-timeout.tooltip=Maksimum tid en bruker har til \u00E5 fullf\u00F8re handlinger relatert til innlogging, som \u00E5 oppdatere passord eller konfigurere TOTP. Det anbefales at denne er relativt lang. 5 minutter eller mer.
+headers=Headere
+brute-force-detection=Deteksjon av Brute Force
+x-frame-options=Alternativer for X-Frame
+x-frame-options-tooltip=Standardverdi hindrer sider fra \u00E5 bli inkludert via non-origin iframes. (Klikk p\u00E5 etikett for mer informasjon)
+content-sec-policy=Sikkerhetspolicy for innhold
+content-sec-policy-tooltip=Standardverdi hindrer sider fra \u00E5 bli inkludert via non-origin iframes. (Klikk p\u00E5 etikett for mer informasjon)
+content-type-options=Alternativer for X-innholdstyper
+content-type-options-tooltip=Standardverdi som forhindrer Internet Explorer og Google Chrome fra \u00E5 MIME-sniffe et svar vekk fra den deklarerte innholdstypen (content-type) (Klikk p\u00E5 etikett for mer informasjon)
+max-login-failures=Maksimum antall innloggingsfeil
+max-login-failures.tooltip=Hvor mange feil f\u00F8r ventetid blir aktivert.
+wait-increment=\u00F8kning av ventetid
+wait-increment.tooltip=N\u00E5r terskelen for feil er n\u00E5dd, hvor lenge skal brukeren stenges ute?
+quick-login-check-millis=Hurtig innlogging - kontroll av millisekunder
+quick-login-check-millis.tooltip=Hvis en feil skjer for raskt samtidig, steng brukeren ute.
+min-quick-login-wait=Minimum ventetid for hurtig innlogging
+min-quick-login-wait.tooltip=Ventetid etter en hurtig innloggingsfeil.
+max-wait=Maksimum ventetid
+max-wait.tooltip=Maksimum tid en bruker vil v\u00E6re stengt ute.
+failure-reset-time=Tid for tilbakestilling av feil.
+failure-reset-time.tooltip=N\u00E5r vil teller for feil nullstilles?
+realm-tab-login=Innlogging
+realm-tab-keys=N\u00F8kler
+realm-tab-email=E-post
+realm-tab-themes=Tema
+realm-tab-cache=Cache
+realm-tab-tokens=Tokens
+realm-tab-client-initial-access=F\u00F8rste access token
+realm-tab-security-defenses=Sikkerhetsmekanismer
+realm-tab-general=Generelt
+add-realm=Legg til sikkerhetsdomene
+
+#Session settings
+realm-sessions=Sikkerhetsdomenesesjoner
+revocation=Oppheving
+logout-all=Logg ut alle
+active-sessions=Aktive sesjoner
+sessions=Sesjoner
+not-before=Ikke f\u00F8r
+not-before.tooltip=Opphev alle tokens utstedt f\u00F8r denne datoen.
+set-to-now=Sett til n\u00E5
+push=Send
+push.tooltip=For enhver klient som har en administratorURL, send dem beskjed om den nye opphevingspolicyen.
+
+#Protocol Mapper
+usermodel.prop.label=Egenskap
+usermodel.prop.tooltip=Navn p\u00E5 egenskapsmetoden i UserModel-grensesnittet. For eksempel, en verdi av 'e-post' vil referere til metoden UserModel.getEmail().
+usermodel.attr.label=Brukerattributt
+usermodel.attr.tooltip=Navn p\u00E5 lagret brukerattributt som er navnet p\u00E5 en attributt innenfor UserModel.attribute map.
+userSession.modelNote.label=Brukersesjonsmerknad
+userSession.modelNote.tooltip=Navn p\u00E5 lagret brukersesjonsmerknad innenfor UserSessionModel.note map.
+multivalued.label=Flere verdier
+multivalued.tooltip=Angir om en attributt st\u00F8tter flere verdier. Hvis true, vil listen med alle verdier for dette attributtet bli satt som claims. Hvis false, vil bare den f\u00F8rste verdien bli satt som claim.
+selectRole.label=Velg rolle
+selectRole.tooltip=Skriv inn rolle i tekstboksen til venstre, eller klikk p\u00E5 denne knappen for \u00E5 bla gjennom og velge rollen du \u00F8nsker.
+tokenClaimName.label=Navn p\u00E5 token claim
+tokenClaimName.tooltip=Navn p\u00E5 claim som skal legges inn i token. Denne kan v\u00E6re et fullt kvalifisert navn som 'address.street'. I dette tilfellet vil et nestet jsonobjekt bli laget.
+jsonType.label=JSON-type for claims
+jsonType.tooltip=JSON-type som burde bli brukt for \u00E5 fylle json claimet i tokenet. long, int, boolean og String er gyldige verdier.
+includeInIdToken.label=Legg til i ID token
+includeInIdToken.tooltip=Burde claim bli lagt til i ID token?
+includeInAccessToken.label=Legg til i access token
+includeInAccessToken.tooltip=Burde claim bli lagt til i access token?
+includeInUserInfo.label=Legg til i brukerinfo
+includeInUserInfo.tooltip=Burde claim bli lagt til i brukerinfo?
+usermodel.clientRoleMapping.clientId.label=Klient-ID
+usermodel.clientRoleMapping.clientId.tooltip=Klient-ID for \u00E5 mappe roller
+usermodel.clientRoleMapping.rolePrefix.label=Prefiks for klientrolle
+usermodel.clientRoleMapping.rolePrefix.tooltip=Prefiks for hver klientrolle (valgfri).
+usermodel.realmRoleMapping.rolePrefix.label=Prefiks for sikkerhetsdomenerolle
+usermodel.realmRoleMapping.rolePrefix.tooltip=Prefiks for hver sikkerhetsdomenerolle (valgfri).
+
+# client details
+clients.tooltip=Klienter er betrodde nettleserapplikasjoner og web-tjenester i et sikkerhetsdomene. Disse klientene kan be om en innlogging. Du kan ogs\u00E5 definere klientspesifikke roller.
+search.placeholder=S\u00F8k...
+create=Opprett
+import=Importer
+client-id=Klient-ID
+base-url=Base URL
+actions=Handlinger
+not-defined=Ikke definert
+edit=Rediger
+delete=Slett
+no-results=Ingen resultater
+no-clients-available=Ingen klienter er tilgjengelige
+add-client=Legg til klient
+select-file=Velg fil
+view-details=Se detaljer
+clear-import=T\u00F8m import
+client-id.tooltip=Angir ID referert i URI og tokens. For eksempel 'min-klient'. For SAML er dette ogs\u00E5 forventet utgiververdi fra authn-foresp\u00F8rsler
+client.name.tooltip=Angir klientnavnet som blir vist. For eksempel, 'Min klient'. St\u00F8tter n\u00F8kler for lokaliserte verdier. For eksempel\: ${my_client}
+client.enabled.tooltip=Deaktiverte klienter kan ikke initiere en innlogging eller motta access tokens.
+consent-required=Samtykke p\u00E5krevd
+consent-required.tooltip=Hvis aktivert m\u00E5 brukere gi samtykke for at klienten skal f\u00E5 tilgang.
+client-protocol=Klientprotokoll
+client-protocol.tooltip='OpenID connect' tillater klienter \u00E5 verifisere identiteten til sluttbrukeren basert p\u00E5 autentisering utf\u00F8rt av en autorisasjonsserver. 'SAML' aktiverer en web-basert autentisering og autoriseringsscenarier som inkluderer cross-domain single sign-on (SSO) og som bruker security tokens som inneholder assertions for \u00E5 dele informasjon videre.
+access-type=Tilgangstype
+access-type.tooltip='Confidential' klienter krever en secret for \u00E5 initiere innloggingsprotokoll. 'Public' klienter krever ikke en secret. 'Bearer-only' klienter er webtjenester som aldri initierer en innlogging.
+standard-flow-enabled=Standard flow aktivert
+standard-flow-enabled.tooltip=Dette aktiverer standard OpenID Connect redirect-basert autentisering med autorisasjonskode. I forhold til OpenID Connect eller OAuth2 spesifikasjoner aktiverer dette st\u00F8tte for 'Authorization Code Flow' for denne klienten.
+implicit-flow-enabled=Implicit flow aktivert
+implicit-flow-enabled.tooltip=Dette aktiverer st\u00F8tte for OpenID Connect redirect-basert autentisering uten autorisasjonskode. I forhold til OpenID Connect eller OAuth2 spesifikasjoner aktiverer dette st\u00F8tte for 'Implicit Flow' for denne klienten.
+direct-access-grants-enabled=Direct access grants aktivert
+direct-access-grants-enabled.tooltip=Dette gir st\u00F8tte for Direct Access Grants, som betyr at klienten har tilgang til brukerens brukernavn/passord og kan bytte dette direkte med Keycloak-serveren for access token. I f\u00F8lge OAuth2 spesifikasjonen, aktiverer dette st\u00F8tte for 'Resource Owner Password Credentials Grant' for denne klienten.
+service-accounts-enabled=Tjenestekonto aktivert
+service-accounts-enabled.tooltip=Lar deg autentisere denne klienten til Keycloak og hente access token dedikert til denne klienten. I f\u00F8lge OAuth2 spesifikasjonen, aktiverer dette st\u00F8tte for 'Client Credentials Grant' for denne klienten.
+include-authnstatement=Inkluder AuthnStatement
+include-authnstatement.tooltip=Skal et statement som spesifiserer metoden for tidsstempel inng\u00E5 i innloggingssvaret?
+sign-documents=Signer dokumenter
+sign-documents.tooltip=Skal SAML dokumenter bli signert av sikkerhetsdomenet?
+sign-assertions=Signer assertions
+sign-assertions.tooltip=Skal assertions i SAML dokumenter bli signert? Denne innstillingen er ikke n\u00F8dvendig hvis et dokument allerede har blitt signert.
+signature-algorithm=Signaturalgoritme
+signature-algorithm.tooltip=Signaturalgoritmen som brukes for \u00E5 signere et dokument.
+canonicalization-method=Kanoniseringsmetode
+canonicalization-method.tooltip=Kanoniseringsmetode for XML signaturer.
+encrypt-assertions=Krypter assertions
+encrypt-assertions.tooltip=Skal SAML assertions bli kryptert med klientens offentlige n\u00F8kkel ved \u00E5 bruke AES?
+client-signature-required=Klientens signatur er p\u00E5krevd
+client-signature-required.tooltip=Skal klienten signere sine SAML foresp\u00F8rsler og svar? Og skal de valideres?
+force-post-binding=Force POST binding
+force-post-binding.tooltip=Bruk alltid POST binding for svar.
+front-channel-logout=Front channel utlogging
+front-channel-logout.tooltip=Hvis satt til true, krever utlogging en redirect i nettleser til klient. Hvis satt til false, vil server utf\u00F8re en bakgrunnskall for utlogging.
+force-name-id-format=Force navn-ID format
+force-name-id-format.tooltip=Ignorer forespurt format p\u00E5 Navn-ID emnet og bruk den som er konfigurert i administrasjonskonsollen.
+name-id-format=Navn-ID format
+name-id-format.tooltip=Navn-ID formatet som skal brukes for emnet.
+root-url=Root URL
+root-url.tooltip=Root URL lagt til relative URLer
+valid-redirect-uris=Gyldig redirect URIer
+valid-redirect-uris.tooltip=Gyldig URI m\u00F8nster som en nettleser kan redirecte til etter en vellykket innlogging eller utlogging. Enkle jokertegn er tillatt, for eksempel 'http://example.com/*'. Relativ sti kan ogs\u00E5 spesifiseres, for eksempel /my/relative/path/*. Relative stier er relative til klientens root URL, eller hvis ingen er spesifisert brukes root URL for autorisasjonsserveren. For SAML m\u00E5 du sette et gyldig URI m\u00F8nster hvis du er avhengig av at URL for forbrukertjenesten er integrert med foresp\u00F8rselen for p\u00E5logging.
+base-url.tooltip=Standard URL som kan brukes n\u00E5r autorisasjonsserveren trenger \u00E5 redirecte eller lenke tilbake til klienten.
+admin-url=Admin URL
+admin-url.tooltip=URL til administratorgrensesnitt for klienten. Sett denne hvis klienten st\u00F8tter adapter REST API. Dette REST APIet tillater autorisasjonsserveren til \u00E5 sende tilbakekallingsregler og andre administrative oppgaver. Vanligvis er dette satt til klientens base URL.
+master-saml-processing-url=Master SAML prosesserings URL
+master-saml-processing-url.tooltip=Hvis konfigurert vil denne URLen bli brukt for hver binding til b\u00E5de SPs Assertion Consumer og Single Logout-tjenester. Denne kan bli individuelt overstyrt for hver binding og tjenester i konfigurasjonen for finkornet SAML endepunkt.
+idp-sso-url-ref=IDP initiert SSO URL navn
+idp-sso-url-ref.tooltip=Navn p\u00E5 URL-fragment som refererer til klienten n\u00E5r du vil gj\u00F8re en IDP initiert SSO. La denne st\u00E5 tom om du \u00F8nsker \u00E5 deaktivere IDP initiert SSO. URLen vil v\u00E6re: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
+idp-sso-relay-state=IDP initiert SSO relay state
+idp-sso-relay-state.tooltip=Relay state du \u00F8nsker \u00E5 sende med SAML foresp\u00F8rselen n\u00E5r du vil utf\u00F8re en IDP initiert SSO.
+web-origins=Web origins
+web-origins.tooltip=Tillat CORS origins. For \u00E5 tillate alle origins med gyldig Redirect URIer legg til '+'. For \u00E5 tillate alle origins legg til '*'.
+fine-saml-endpoint-conf=Finkornet SAML endepunktskonfigurasjon
+fine-saml-endpoint-conf.tooltip=Utvid denne delen til \u00E5 konfigurere n\u00F8yaktige URLer for Assertion Consumer og Single Logout-tjeneste.
+assertion-consumer-post-binding-url=Assertion consumer service POST binding URL
+assertion-consumer-post-binding-url.tooltip=SAML POST binding URL for klientens assertion customer service (innloggingsrespons). Du kan la denne st\u00E5 tom om du ikke \u00F8nsker en URL for denne bindingen.
+assertion-consumer-redirect-binding-url=Assertion Consumer Service redirect binding URL
+assertion-consumer-redirect-binding-url.tooltip=SAML redirect for klientens assertion consumer service (innloggingsrespons). Du kan la denne st\u00E5 tom om du ikke \u00F8nsker en URL for denne bindingen.
+logout-service-binding-post-url=logout-tjeneste POST binding URL
+logout-service-binding-post-url.tooltip=SAML POST binding URL for klientens single logout-tjeneste. Du kan la dette st\u00E5 tomt om du bruker en annen binding.
+logout-service-redir-binding-url=Logout-tjeneste redirect binding URL
+logout-service-redir-binding-url.tooltip=SAML redirect binding URL for klientens single logout-tjeneste. Du kan la dette st\u00E5 tomt om du bruker en annen binding.
+
+# client import
+import-client=Importer klient
+format-option=Formatalternativer
+select-format=Velg et format
+import-file=Importer fil
+
+# client tabs
+settings=Innstillinger
+credentials=Innloggingsdetaljer
+saml-keys=SAML n\u00F8kler
+roles=Roller
+mappers=Mappere
+mappers.tooltip=Protokollmappere som utf\u00F8rer endringer av tokens og dokumenter. De kan utf\u00F8re handlinger som \u00E5 mappe brukerdata til protokollclaims, eller bare endre foresp\u00F8rsler som blir sendt mellom klienten og autorisasjonsserver.
+scope=Scope
+scope.tooltip=Mapping av scope lar deg begrense hvilke rollemappinger som er inkludert i access token som klienten har bedt om.
+sessions.tooltip=Viser aktive sesjoner for denne klienten. Tillater deg \u00E5 se hvilke brukere som er aktive og n\u00E5r de logget inn.
+offline-access=Frakoblet tilgang
+offline-access.tooltip=Viser frakoblede sesjoner for denne klienten. Tillater deg \u00E5 se hvilke brukere som henter tokens for frakoblet modus og n\u00E5r de henter den. For \u00E5 tilbakekalle alle tokens for klienten, g\u00E5 til fanen Opphev og sett verdien for Ikke f\u00F8r til n\u00E5.
+clustering=Clustering
+installation=Installasjon
+installation.tooltip=Verkt\u00F8y for \u00E5 generere ulike konfigurasjonsformater for klientadapter som du kan laste ned eller klippe og lime inn for \u00E5 konfigurere klientene dine.
+service-account-roles=Tjenestekonto-roller
+service-account-roles.tooltip=Tillater deg \u00E5 autentisere rollemappinger for tjenestekontoen som er dedikert til denne klienten.
+
+# client credentials
+client-authenticator=Klientautentikator
+client-authenticator.tooltip=Klientautentikator som blir brukt for \u00E5 autentisere denne klienten mot keycloak-server
+certificate.tooltip=Klientsertifikat for \u00E5 validere JWT utstedt av klienten og signert av privatn\u00F8kkel til klient fra din keystore.
+publicKey.tooltip=Offentlig n\u00F8kkel for \u00E5 validere JWT utstedt av klient og signert av klientens privatn\u00F8kkel.
+no-client-certificate-configured=Ingen klientsertifikat er konfigurert
+gen-new-keys-and-cert=Generer nye n\u00F8kler og sertifikater
+import-certificate=Importer sertifikat
+gen-client-private-key=Generer privatn\u00F8kkel for klient
+generate-private-key=Generer privatn\u00F8kkel
+archive-format=Arkivformat
+archive-format.tooltip=Java keystore eller PKCS12 arkivformat.
+key-alias=N\u00F8kkelalias
+key-alias.tooltip=Arkiv-alias for din privatn\u00F8kkel og sertifikater.
+key-password=N\u00F8kkelpassord
+key-password.tooltip=Passord for \u00E5 f\u00E5 tilgang til privatn\u00F8kler i arkivet
+store-password=Lagre passord
+store-password.tooltip=Passord for \u00E5 f\u00E5 tilgang til arkivet
+generate-and-download=Generer og Last ned
+client-certificate-import=Import av klientsertifikat
+import-client-certificate=Importer klientsertifikat
+jwt-import.key-alias.tooltip=Arkiv-alias for sertifikatet ditt.
+secret=Secret
+regenerate-secret=Regenere secret
+registrationAccessToken=Access token for registrering
+registrationAccessToken.regenerate=Regenerer access token for registrering
+registrationAccessToken.tooltip=Access token for registrering gir klienter tilgang til registreringstjenesten for klienter.
+add-role=Legg til rolle
+role-name=Rollenavn
+composite=Sammensatt
+description=Beskrivelse
+no-client-roles-available=Ingen klientroller er tilgjengelig
+scope-param-required=Scope parameter p\u00E5krevd
+scope-param-required.tooltip=Denne rollen vil kun bli gitt hvis parameter for scope med rollenavn blir brukt under foresp\u00F8rsel av autorisasjon/token.
+composite-roles=Sammensatte roller
+composite-roles.tooltip=N\u00E5r denne rollen er tildelt/ikke tildelt til en bruker, vil hvilken som helst rolle assosiert med denne bli implisitt tildelt/ikke tildelt.
+realm-roles=Sikkerhetsdomeneroller
+available-roles=Tilgjengelig roller
+add-selected=Legg til valgte
+associated-roles=Assosierte roller
+composite.associated-realm-roles.tooltip=Sikkerhetsdomeneniv\u00E5-rolle knyttet til denne sammensatte rollen.
+composite.available-realm-roles.tooltip=Sikkerhetsdomeneniv\u00E5-roller knyttet til denne sammensatte rollen.
+remove-selected=Fjern valgte
+client-roles=Klientroller
+select-client-to-view-roles=Velg klient for \u00E5 se roller for klient
+available-roles.tooltip=Roller fra denne klienten som du kan knytte til denne sammensatte rollen.
+client.associated-roles.tooltip=Klientrolle assosiert med denne sammensatte rollen.
+add-builtin=Legg til Builtin
+category=Kategori
+type=Type
+no-mappers-available=Ingen mappere er tilgjengelig
+add-builtin-protocol-mappers=Legg til Builtin protokollmappere
+add-builtin-protocol-mapper=Legg til Builtin protokollmapper
+scope-mappings=Scopemapping
+full-scope-allowed=Tillatt med fullt scope
+full-scope-allowed.tooltip=Lar deg \u00E5 deaktivere alle restriksjoner.
+scope.available-roles.tooltip=Sikkerhetsdomeneniv\u00E5-roller som kan bli tildelt til scope.
+assigned-roles=Tildelte roller
+assigned-roles.tooltip=Sikkerhetsdomeneniv\u00E5-roller tildelt til scope.
+effective-roles=Effektive roller
+realm.effective-roles.tooltip=Tildelte sikkerhetsdomeneniv\u00E5-roller som kan ha blitt arvet fra en sammensatt rolle.
+select-client-roles.tooltip=Velg en klient for \u00E5 se roller for klient
+assign.available-roles.tooltip=Klientroller som er tilgjengelige til \u00E5 bli tildelt.
+client.assigned-roles.tooltip=Tildelte klientroller.
+client.effective-roles.tooltip=Tildelte klientroller som kan ha blitt arvet fra en sammensatt rolle.
+basic-configuration=Basiskonfigurasjon
+node-reregistration-timeout=Timeout for re-registrering av node
+node-reregistration-timeout.tooltip=Intervall for \u00E5 angi maksimum tid for registrerte klienters clusternoder for \u00E5 re-registreres. Hvis en clusternode ikke sender re-regisreringsforesp\u00F8rsel til Keycloak innen dette intervallet, vil den bli uregistrert fra Keycloak.
+registered-cluster-nodes=Registrerte clusternoder
+register-node-manually=Register node manuelt
+test-cluster-availability=Test cluster tilgjengelighet
+last-registration=Siste registrering
+node-host=Nodevert
+no-registered-cluster-nodes=Ingen registrerte clusternoder tilgjengelig
+cluster-nodes=Clusternoder
+add-node=Legg til node
+active-sessions.tooltip=Totalt antall aktive brukersesjoner for denne klienten.
+show-sessions=Vis sesjoner
+show-sessions.tooltip=Advarsel, dette er en potensielt kostbar operasjon avhengig av antall aktive sesjoner.
+user=Bruker
+from-ip=Fra IP
+session-start=Start av sesjon
+first-page=F\u00F8rste side
+previous-page=Forrige side
+next-page=Neste side
+client-revoke.not-before.tooltip=Opphev alle token utstedt f\u00F8r denne datoen for denne klienten.
+client-revoke.push.tooltip=Hvis administrator URL er konfigurert for denne klienten, dytt denne policyen p\u00E5 denne klienten.
+select-a-format=Velg et format
+download=Last ned
+offline-tokens=Offline tokens
+offline-tokens.tooltip=Totalt antall offline tokens for denne klienten.
+show-offline-tokens=Vis offline tokens
+show-offline-tokens.tooltip=Advarsel, dette er en potensielt kostbar operasjon avhengig av antall offline tokens.
+token-issued=Utgitt token
+last-access=Sist aksessert
+last-refresh=Siste refresh
+key-export=Eksporter n\u00F8kkel
+key-import=Importer n\u00F8kkel
+export-saml-key=Eksporter SAML n\u00F8kkel
+import-saml-key=Importer SAML n\u00F8kkel
+realm-certificate-alias=Alias for sikkerhetsdomenesertifikat
+realm-certificate-alias.tooltip=Sertifikat for sikkerhetsdomenet er ogs\u00E5 lagret i arkivet. Dette er aliaset.
+signing-key=Signeringsn\u00F8kkel
+saml-signing-key=SAML signeringsn\u00F8kkel
+private-key=Privatn\u00F8kkel
+generate-new-keys=Generer nye n\u00F8kler
+export=Eksporter
+encryption-key=Krypteringsn\u00F8kkel
+saml-encryption-key.tooltip=SAML krypteringsn\u00F8kkel.
+service-accounts=Tjenestekonto-konto
+service-account.available-roles.tooltip=Sikkerhetsdomeneniv\u00E5-roller som kan bli tildelt til tjeneste-konto.
+service-account.assigned-roles.tooltip=Sikkerhetsdomeneniv\u00E5-roller tildelt service-konto.
+service-account-is-not-enabled-for=Tjeneste-konto er ikke aktivert for {{client}}
+create-protocol-mappers=Opprett protokollmappere
+create-protocol-mapper=Opprett protokollmapper
+protocol=Protokoll
+protocol.tooltip=Protokoll...
+id=ID
+mapper.name.tooltip=Navn p\u00E5 mapper.
+mapper.consent-required.tooltip=Ved tildeling av midlertidig tilgang m\u00E5 brukeren samtykke til \u00E5 gi denne informasjonen til klienten?
+consent-text=Samtykketekst
+consent-text.tooltip=Tekst som blir vist p\u00E5 side for samtykke.
+mapper-type=Mappertype
+mapper-type.tooltip=Type mapper
+# realm identity providers
+identity-providers=Identitetsleverand\u00F8r
+table-of-identity-providers=Liste over identitetsleverand\u00F8rer
+add-provider.placeholder=Legg til leverand\u00F8r...
+provider=Leverand\u00F8r
+gui-order=Rekkef\u00F8lge for brukergrensesnitt
+first-broker-login-flow=Flyt for f\u00F8rste innlogging
+post-broker-login-flow=Post-p\u00E5loggingsflyt
+redirect-uri=Redirect URI
+redirect-uri.tooltip=Redirect URI som skal brukes n\u00E5r du konfigurerer identitetsleverand\u00F8ren.
+alias=Alias
+identity-provider.alias.tooltip=Aliaset identifiserer en identitetsleverand\u00F8r og kan brukes for \u00E5 bygge en redirect uri.
+identity-provider.enabled.tooltip=Aktiver/deaktiver denne identitetsleverand\u00F8ren.
+authenticate-by-default=Autentiser som standard
+identity-provider.authenticate-by-default.tooltip=Indikerer om en leverand\u00F8r burde fors\u00F8kes \u00E5 brukes om standard for autentisering selv om innloggingssiden enda ikke har blitt vist.
+store-tokens=Lagre Tokens
+identity-provider.store-tokens.tooltip=Aktiver/deaktiver hvis tokens m\u00E5 bli lagret etter at brukere har blitt autentisert.
+stored-tokens-readable=Lagrede lesbare tokens
+identity-provider.stored-tokens-readable.tooltip=Aktiver/deaktiver hvis nye brukere kan lese lagrede tokens. Dette tildeles broker.read-token rollen.
+update-profile-on-first-login=Oppdater profil ved f\u00F8rste innlogging
+on=P\u00E5
+on-missing-info=Ved manglende informasjon
+off=Av
+update-profile-on-first-login.tooltip=Definer vilk\u00E5rene en bruker m\u00E5 oppfylle for \u00E5 oppdatere sin profil ved f\u00F8rste innlogging.
+trust-email=Stol p\u00E5 e-post
+trust-email.tooltip=Hvis aktivert vil ikke e-post levert av denne leverand\u00F8ren bli verifisert selv om verifisering er aktivert for sikkerhetsdomenet.
+gui-order.tooltip=Antall som angir rekkef\u00F8lgen av leverand\u00F8rer i brukergrensesnittet (For eksempel p\u00E5 innloggingssiden).
+first-broker-login-flow.tooltip=Alias for autentiseringsflyt, som trigges etter f\u00F8rste innlogging med denne identitetsleverand\u00F8ren. Begrepet 'F\u00F8rste innlogging' betyr at det enn\u00E5 ikke eksisterer en Keycloak-konto koblet til den autentiserte kontoen til identitetsleverand\u00F8ren.
+post-broker-login-flow.tooltip=Alias for autentiseringsflyt, som trigges etter hver innlogging med denne identitetsleverand\u00F8ren. Nyttig om man \u00F8nsker tilleggsverifikasjon av hver bruker autentisert med denne identitetsleverand\u00F8ren (for eksempel med engangskode/engangspassord). La denne st\u00E5 tom om du ikke \u00F8nsker at tilleggautentisering skal bli trigget etter en innlogging med denne identitetsleverand\u00F8ren. Merk ogs\u00E5 at implementasjonen av denne autentikatoren m\u00E5 anta at bruker allerede er satt i ClientSession ettersom identitetsleverand\u00F8ren allerede setter det.
+openid-connect-config=OpenID Connect konfigurasjon
+openid-connect-config.tooltip=OIDC SP og ekstern IDP-konfigurasjon.
+authorization-url=Autorisasjons URL
+authorization-url.tooltip=Autorisasjons URLen.
+token-url=Token URL
+token-url.tooltip=Token URLen.
+logout-url=Utloggings URL
+identity-provider.logout-url.tooltip=Endepunkt for avsluttende sesjon som brukes for \u00E5 logge ut bruker fra ekstern IDP.
+backchannel-logout=Backchannel utlogging
+backchannel-logout.tooltip=St\u00F8tter ekstern IDP backchannel utlogging?
+user-info-url=Brukerinfo URL
+user-info-url.tooltip=Brukerinfo URLen. Denne er valgfri.
+identity-provider.client-id.tooltip=Klienten eller klientidentifikator registrert hos identitetsleverand\u00F8ren.
+client-secret=Klient secret
+show-secret=Vis secret
+hide-secret=Skjul secret
+client-secret.tooltip=Klienten eller klient secret registrert hos identitetsleverand\u00F8ren.
+issuer=Utgiver
+issuer.tooltip=Identifikator for utgiver av foresp\u00F8rselen. Hvis dette ikke er oppgitt vil ingen validering utf\u00F8res.
+default-scopes=Standard Scopes
+identity-provider.default-scopes.tooltip=Scopes som sendes n\u00E5r du ber om autorisasjon. Dette kan v\u00E6re en liste med scopes separert med mellomrom. Standard er satt til 'openid'.
+prompt=Prompt
+unspecified.option=uspesifisert
+none.option=Ingen
+consent.option=samtykke
+login.option=Innlogging
+select-account.option=velg_konto (select_account)
+prompt.tooltip=Spesifiserer om autorisasjonsserver skal be sluttbruker om re-autentisering og samtykke.
+validate-signatures=Valider signaturer
+identity-provider.validate-signatures.tooltip=Aktiver/deaktiver signaturvalidering av eksterne IDP signaturer.
+validating-public-key=Valider offentlig n\u00F8kkel
+identity-provider.validating-public-key.tooltip=PEM format for offentlig n\u00F8kkel som m\u00E5 brukes for \u00E5 kontrollere eksterne IDP signaturer.
+import-external-idp-config=Importer ekstern IDP konfigurasjon
+import-external-idp-config.tooltip=Lar deg laste inn ekstern IDP metadata fra en konfigurasjonsfil eller ved \u00E5 laste det ned fra en URL.
+import-from-url=Importer fra URL
+identity-provider.import-from-url.tooltip=Importer metadata fra et eksternt IDP discovery descriptor.
+import-from-file=Importer fra fil
+identity-provider.import-from-file.tooltip=Importer metadata fra en nedlastet IDP discovery descriptor.
+saml-config=SAML konfigurasjon
+identity-provider.saml-config.tooltip=SAML SP og ekstern IDP konfigurasjon.
+single-signon-service-url=Single sign-on service URL
+saml.single-signon-service-url.tooltip=URL som m\u00E5 brukes for \u00E5 sende autentiseringsforesp\u00F8rsler (SAML AuthnRequest).
+single-logout-service-url=Single utloggingstjeneste URL
+saml.single-logout-service-url.tooltip=URL som m\u00E5 brukes for \u00E5 sende utloggingsforesp\u00F8rsler.
+nameid-policy-format=Policy for nameid-format
+nameid-policy-format.tooltip=Angir URI-referanse som tilsvarer et format for identifikator-navn. Standard er satt til urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
+http-post-binding-response=HTTP-POST binding svar
+http-post-binding-response.tooltip=Indikerer om man skal svare p\u00E5 foresp\u00F8rsler som bruker HTTP-POST binding eller ikke. Hvis satt til false, vil HTTP-REDIRECT binding bli brukt.
+http-post-binding-for-authn-request=HTTP-POST binding for AuthnRequest
+http-post-binding-for-authn-request.tooltip=Indikerer om AuthnRequests m\u00E5 bli sendt ved \u00E5 bruke en HTTP-POST binding. Hvis satt til false, vil HTTP-REDIRECT binding bli brukt.
+want-authn-requests-signed=Vil ha AuthnRequests signert
+want-authn-requests-signed.tooltip=Indikerer om identitetsleverand\u00F8r forventer en signert AuthnRequest.
+force-authentication=Force autentisering
+identity-provider.force-authentication.tooltip=Indikerer om identitetsleverand\u00F8r m\u00E5 autentisere presentat\u00F8ren direkte i stedet for \u00E5 stole p\u00E5 en tidligere sikkerhetskontekst.
+validate-signature=Valider signatur
+saml.validate-signature.tooltip=Aktiver/deaktiver signaturvalidering av SAML svar.
+validating-x509-certificate=Validerer X509 sertifikat
+validating-x509-certificate.tooltip=Sertifikatet i PEM format som m\u00E5 brukes for \u00E5 se etter signaturer.
+saml.import-from-url.tooltip=Importer metadata fra et eksternt IDP SAML entity descriptor.
+social.client-id.tooltip=Identifikator for klient registrert hos identitetsleverand\u00F8r.
+social.client-secret.tooltip=Klient secret registrert hos identitetsleverand\u00F8r.
+social.default-scopes.tooltip=Scopes som sendes n\u00E5r tillatelse for autorisasjon blir etterspurt. Se dokumentasjon for mulige verdier, separator og standardverdi.
+key=N\u00F8kkel
+stackoverflow.key.tooltip=N\u00F8kkelen er hentet fra klientregistrering p\u00E5 Stack Overflow.
+
+# User federation
+sync-ldap-roles-to-keycloak=Synkroniser LDAP-roller til Keycloak
+sync-keycloak-roles-to-ldap=Synkroniser Keycloak-roller til LDAP
+sync-ldap-groups-to-keycloak=Synkroniser LDAP-grupper til Keycloak
+sync-keycloak-groups-to-ldap=Synkroniser Keycloak-grupper til LDAP
+
+realms=Sikkerhetsdomener
+realm=Sikkerhetsdomene
+
+identity-provider-mappers=Identitetsleverand\u00F8rmappere
+create-identity-provider-mapper=Opprett identitetsleverand\u00F8rmappere
+add-identity-provider-mapper=Legg til identitetsleverand\u00F8rmappere
+client.description.tooltip=Angir beskrivelse av klienten. For eksempel\: 'Min klient for timelister'. St\u00F8tter n\u00F8kler for lokaliserte verdier. For eksempel\: ${my_client_description}
+
+expires=Utl\u00F8per
+expiration=Holdbarhet
+expiration.tooltip=Angir hvor lenge et token skal v\u00E6re gyldig
+count=Teller
+count.tooltip=Angir hvor mange klienter som kan bli opprettet ved \u00E5 bruke token.
+remainingCount=Resterende antall
+created=Opprettet
+back=Tilbake
+initial-access-tokens=F\u00F8rste access tokens
+initial-access-tokens.tooltip=F\u00F8rste access tokens for dynamisk registrering av klienter. Foresp\u00F8rsler med disse tokens kan bli sent fra alle verter.
+add-initial-access-tokens=Legg til f\u00F8rste access token
+initial-access-token=F\u00F8rste access token
+initial-access.copyPaste.tooltip=Kopier/lim inn f\u00F8rste access token f\u00F8r du navigerer vekk fra denne siden ettersom det ikke er mulig \u00E5 hente den senere.
+continue=Fortsett
+initial-access-token.confirm.title=Kopier f\u00F8rste access token
+initial-access-token.confirm.text=Vennligst kopier og lim inn f\u00F8rste access token f\u00F8r du bekrefter ettersom den ikke kan hentes senere
+no-initial-access-available=F\u00F8rste access token er ikke tilgjengelig
+
+trusted-hosts-legend=Betrodde verter for klientregistrering
+trusted-hosts-legend.tooltip=Verter, som er betrodd for klientregistrering. klientregistreringsforesp\u00F8rsler fra disse vertene kan bli sent selv uten f\u00F8rste access token. Antall klientregistreringer fra denne spesifikke verten kan bli begrenset til et spesifisert antall.
+no-client-trusted-hosts-available=Ingen betrodde verter er tilgjengelig
+add-client-reg-trusted-host=Legg til betrodd vert
+hostname=Vertsnavn
+client-reg-hostname.tooltip=Vertsnavn eller IP-adresse. Klientregistreringsforesp\u00F8rsler fra denne verten/adressen vil bli betrodd og tillat til \u00E5 registrere en ny klient.
+client-reg-count.tooltip=Tillat antall klientregistreringsforesp\u00F8rsler fra en spesifikk vert. Du m\u00E5 restarte denne n\u00E5r grensen er n\u00E5dd.
+client-reg-remainingCount.tooltip=Gjenv\u00E6rende antall klientregistreringsforesp\u00F8rsler fra denne verten. Du m\u00E5 restarte denne n\u00E5r grensen er n\u00E5dd.
+reset-remaining-count=Tilbakestill gjenst\u00E5ende antall
+
+client-templates=Klientmaler
+client-templates.tooltip=Klientmaler tillater deg \u00E5 definere felles konfigurasjon som er delt av flere klienter.
+
+groups=Grupper
+
+group.add-selected.tooltip=Sikkerhetsdomene-roller som kan bli tildelt gruppen.
+group.assigned-roles.tooltip=Sikkerhetsdomene-roller mappet til gruppen.
+group.effective-roles.tooltip=Alle sikkerhetsdomene-rollemappinger. Noen roller kan ha blitt arvet fra en sammensatt rolle.
+group.available-roles.tooltip=Roller som kan tildeles fra denne klienten.
+group.assigned-roles-client.tooltip=Rollemapping for denne klienten.
+group.effective-roles-client.tooltip=Rollemapping for denne klienten. Noen roller kan ha blitt arvet fra en mappet sammensatt rolle.
+
+default-roles=Standardroller
+no-realm-roles-available=Ingen sikkerhetsdomener er tilgjengelig
+
+users=Brukere
+user.add-selected.tooltip=Sikkerhetsdomene-roller som kan bli tildelt bruker.
+user.assigned-roles.tooltip=Sikkerhetsdomene-roller mappet til bruker
+user.effective-roles.tooltip=Alle sikkerhetsdomene-rollemappinger. Noen roller kan ha blitt arvet fra en sammensatt rolle.
+user.available-roles.tooltip=Roller som kan tildeles fra denne klienten.
+user.assigned-roles-client.tooltip=Rollemapping for denne klienten.
+user.effective-roles-client.tooltip=Rollemapping for denne klienten. Noen roller kan ha blitt arvet fra en mappet sammensatt rolle.
+default.available-roles.tooltip=Sikkerhetsdomene-roller som kan tildeles.
+realm-default-roles=Standardroller for sikkerhetsdomene
+realm-default-roles.tooltip=Sikkerhetsdomene-roller tildelt nye brukere.
+default.available-roles-client.tooltip=Roller fra denne klienten som blir tildelt som standard.
+client-default-roles=Standard klientroller
+client-default-roles.tooltip=Roller fra denne klienten blir tildelt som standardrolle.
+composite.available-roles.tooltip=Sikkerhetsdomene-roller knyttet til denne sammensatte rollen.
+composite.associated-roles.tooltip=Sikkerhetsdomeneniv\u00E5-roller knyttet til denne sammensatte rollen.
+composite.available-roles-client.tooltip=Roller fra denne klienten kan du assosiere med denne sammensatte rollen.
+composite.associated-roles-client.tooltip=Klientroller knyttet til denne sammensatte rollen.
+partial-import=Delvis import
+partial-import.tooltip=Delvis import lar deg importere brukere, klienter og andre ressurser fra en tidligere eksportert json-fil.
+
+file=File
+exported-json-file=Eksporter json-fil
+import-from-realm=Importer fra sikkerhetsdomene
+import-users=Importer brukere
+import-groups=Importer grupper
+import-clients=Importer klienter
+import-identity-providers=Importer identitetsleverand\u00F8rer
+import-realm-roles=Importer roller for sikkerhetsdomene
+import-client-roles=Importer klientroller
+if-resource-exists=Hvis en ressurs eksisterer
+fail=Mislykkes
+skip=Hopp over
+overwrite=Skriv over
+if-resource-exists.tooltip=Spesifiser hva som skal gj\u00F8res om du fors\u00F8ker \u00E5 importere en ressurs som allerede eksisterer.
+
+action=Handling
+role-selector=Rollevelger
+realm-roles.tooltip=Rolle for sikkerhetsdomene som kan velges.
+
+select-a-role=Velg en rolle
+select-realm-role=Velg en rolle for sikkerhetsdomenet
+client-roles.tooltip=Klientroller som kan velges.
+select-client-role=Velg klientrolle
+
+client-template=Klientmal
+client-template.tooltip=Klientmal som denne klienten arver konfigurasjonen fra
+client-saml-endpoint=Endepunkt for klient-SAML
+add-client-template=Legg til klientmal
+
+manage=H\u00E5ndter
+authentication=Autentisering
+user-storage=Brukerlagring
+user-federation=Brukerfederering
+events=Hendelser
+realm-settings=Innstillinger for sikkerhetsdomene
+configure=Konfigurer
+select-realm=Velg sikkerhetsdomene
+add=Legg til
+
+client-template.name.tooltip=Navn p\u00E5 klientmal. M\u00E5 v\u00E6re unik i sikkerhetsdomenet.
+client-template.description.tooltip=Beskrivelse av klientmal
+client-template.protocol.tooltip=Hvilken SSO protokoll-konfigurasjon som blir levert av denne klientmalen
+
+add-user-federation-provider=Legg til leverand\u00F8r for brukerfederering
+add-user-storage-provider=Legg til brukerlagringsleverand\u00F8r
+required-settings=P\u00E5krevde innstillinger
+provider-id=Leverand\u00F8r-ID
+console-display-name=Konsoll vis navn
+console-display-name.tooltip=Viser navn p\u00E5 leverand\u00F8r n\u00E5r den er lenket i administratorkonsollen.
+priority=Prioritet
+priority.tooltip=Prioritet av leverand\u00F8r n\u00E5r et oppslag av bruker utf\u00F8res. Lavest f\u00F8rst.
+sync-settings=Innstillinger for synkronisering
+periodic-full-sync=Fullstendig periodisk synkronisering
+periodic-full-sync.tooltip=Skal fullstendig periodisk synkronisering av leverand\u00F8r-brukere til Keycloak v\u00E6re aktivert eller deaktivert
+full-sync-period=Fullstendig synkroniseringsperiode
+full-sync-period.tooltip=Periode for fullstendig synkronisering i sekunder
+periodic-changed-users-sync=Periodisk synkronisering av endrede brukere
+periodic-changed-users-sync.tooltip=Skal periodisk synkronisering av endrede eller nylig opprettede leverand\u00F8r-brukere til Keycloak v\u00E6re aktivert eller deaktivert
+changed-users-sync-period=Synkroniseringsperiode for endrede brukere
+changed-users-sync-period.tooltip=Periode for synkronisering av endrede eller nylig opprettede leverand\u00F8r-brukere i sekunder.
+synchronize-changed-users=Synkroniser endrede brukere
+synchronize-all-users=Synkroniser alle brukere
+kerberos-realm=Sikkerhetsdomene for Kerberos
+kerberos-realm.tooltip=Navn p\u00E5 kerberos-sikkerhetsdomene. For eksempel FOO.ORG
+server-principal=Server principal
+server-principal.tooltip=Fullstendig navn p\u00E5 server principal for HTTP-service som inkluderer server og domenenavn. For eksempel HTTP/host.foo.org@FOO.ORG
+keytab=KeyTab
+keytab.tooltip=Plassering av Kerberos-keytab fil som inneholder legitimasjonsdetaljer for server principal. For eksempel /etc/krb5.keytab
+debug=Feils\u00F8king
+debug.tooltip=Aktiver/deaktiver logging av feils\u00F8king til standard output for Krb5LoginModule.
+allow-password-authentication=Tillat autentisering med passord
+allow-password-authentication.tooltip=Aktiver/deaktivert muligheten for autentisering med brukernavn/passord mot databasen til Kerberos
+edit-mode=Redigeringsmodus
+edit-mode.tooltip=READ_ONLY betyr at passordoppdateringer ikke er tillatt, og at bruker alltid autentiseres med et Kerberos-passord. UNSYNCED betyr at bruker kan endre sitt passord i databasen til Keycloak og at denne vil bli brukt i stedet for Kerberos-passordet.
+ldap.edit-mode.tooltip=READ_ONLY er et skrivebeskyttet LDAP-lager. WRITABLE betyr at data vil bli synkronisert tilbake til LDAP p\u00E5 foresp\u00F8rsel. UNSYNCED betyr at brukerdata vil bli importert, men vil ikke bli synkronisert tilbake til LDAP.
+update-profile-first-login=Oppdater profil ved f\u00F8rste innlogging
+update-profile-first-login.tooltip=Oppdater profil ved f\u00F8rste innlogging
+sync-registrations=Synkroniser registreringer
+ldap.sync-registrations.tooltip=Skal nylig opprettede brukere bli opprettet innenfor et LDAP-lager? Prioritet p\u00E5virker hvilken leverand\u00F8r som er valgt for \u00E5 synkronisere den nye brukeren.
+vendor=Leverand\u00F8r
+ldap.vendor.tooltip=LDAP leverand\u00F8r (provider)
+username-ldap-attribute=Brukernavn LDAP-attributt
+ldap-attribute-name-for-username=LDAP-attributtnavn for brukernavn
+username-ldap-attribute.tooltip=Navn p\u00E5 LDAP-attributt, som er kartlagt som et Keycloak-brukernavn. For mange LDAP-serverleverand\u00F8rer kan dette v\u00E6re 'uid'. For Active directory kan dette v\u00E6re 'sAMAccountName' eller 'cn'. Attributtet burde v\u00E6re fylt for alle LDAP-brukeroppf\u00F8ringer om du vil importere fra LDAP til Keycloak.
+rdn-ldap-attribute=RDN LDAP-attributt
+ldap-attribute-name-for-user-rdn=LDAP-attributtnavn for RDN-bruker
+rdn-ldap-attribute.tooltip=Navn p\u00E5 LDAP-attributt, som brukes som RDN (topp-attributt) for en typisk DN-bruker. Vanligvis er dette det samme som LDAP-attributtet for brukernavn, men det er ikke p\u00E5krevd. For eksempel for Active directory er det vanlig \u00E5 bruke cn' som RDN-attributt n\u00E5r attributtet for brukernavn kan v\u00E6re 'sAMAccountName'.
+uuid-ldap-attribute=UUID LDAP-attributt
+ldap-attribute-name-for-uuid=LDAP-attributtnavn for UUID.
+uuid-ldap-attribute.tooltip=Navn p\u00E5 LDAP-attributtet, som brukes som en unik objekt-identifikator (UUID) for objekter i LDAP. For mange LDAP-serverleverand\u00F8rer er det 'entryUUID', men noen er annerledes. For eksempel for Active directory b\u00F8r det v\u00E6re 'objectGUID'. Hvis din LDAP-server ikke st\u00F8tter UUID, kan du bruke hvilket som helst annet attributt, som er ment \u00E5 v\u00E6re unikt blant LDAP-brukere i treet. For eksempel 'uid' eller 'entryDN'.
+user-object-classes=Brukerobjektklasser
+ldap-user-object-classes.placeholder=Objektklasser for LDAP-bruker (separert med komma)
+
+ldap-connection-url=LDAP tilkoblings URL
+ldap-users-dn=LDAP brukere DN
+ldap-bind-dn=LDAP bind DN
+ldap-bind-credentials=LDAP bind innloggingsdetaljer
+ldap-filter=LDAP filter
+ldap.user-object-classes.tooltip=Alle verdier av LDAP objectClass-attributtet for brukere i LDAP er separert med komma. For eksempel, 'inetOrgPerson, organizationalPerson'. Nylig opprettede Keycloak-brukere vil bli skrevet til LDAP med alle disse objektklassene og eksisterende LDAP-brukeroppf\u00F8ringer vil bli funnet om de inneholder de samme objektklassene.
+
+connection-url=Tilkoblings URL
+ldap.connection-url.tooltip=Tilkoblings URL din til LDAP-server
+test-connection=Testkobling
+users-dn=DN-brukere
+ldap.users-dn.tooltip=Fullstendig DN av LDAP-tre hvor dine brukere befinner seg. Denne spesifikke DN er forelder til LDAP-brukere. Den kan for eksempel v\u00E6re 'ou=users,dc=example,dc=com' hvis din typiske bruker vil ha en DN som 'uid=john,ou=users,dc=example,dc=com'
+authentication-type=Autentiseringstype
+ldap.authentication-type.tooltip=LDAP Autentiseringstype. For \u00F8yeblikket er kun mekanismene 'ingen' (anonym LDAP autentisering) eller 'enkel' (bind innloggingsdetaljer) tilgjengelig.
+bind-dn=Bind DN
+ldap.bind-dn.tooltip=DN av LDAP-administrator, som kan brukes av Keycloak for \u00E5 aksessere LDAP-server
+bind-credential=Bind innloggingsdetaljer
+ldap.bind-credential.tooltip=Passord for LDAP administrator
+test-authentication=Testautentisering
+custom-user-ldap-filter=Egendefinert filter for LDAP-bruker
+ldap.custom-user-ldap-filter.tooltip=TilleggsLDAP-filter for \u00E5 filtrere s\u00F8kte brukere. La filteret v\u00E6re tomt om du ikke trenger et ekstra filter. Pass p\u00E5 at den starter med '(' og slutter med ')'
+search-scope=Scope for s\u00F8k
+ldap.search-scope.tooltip=For et niv\u00E5 s\u00F8ker vi etter brukere kun i DNser spesifisert av bruker-DNser. For subtre s\u00F8ker vi i hele subtreet. Se LDAP dokumentasjon for mer informasjon.
+use-truststore-spi=Bruk Truststore SPI
+ldap.use-truststore-spi.tooltip=Spesifiserer om LDAP-koblingen vil bruke truststore SPI med truststore konfigurert i keycloak-server.json. 'Alltid' betyr at den alltid vil brukes. 'Aldri' betyr at den ikke brukes. 'Kun for ldaps' betyr at den vil brukes hvis din koblings URL bruker ldaps. Merk at selv om keycloak-server.json ikke er konfigurert, vil default Java cacerts eller sertifikat spesifisert i 'javax.net.ssl.trustStore' bli brukt.
+connection-pooling=Connection Pooling
+ldap.connection-pooling.tooltip=Burde Keycloak bruke connection pooling for \u00E5 aksessere LDAP-serveren?
+ldap.pagination.tooltip=St\u00F8tter LDAP-serveren paginering?
+kerberos-integration=Kerberos Integrasjon
+allow-kerberos-authentication=Tillat autentisering med Kerberos
+ldap.allow-kerberos-authentication.tooltip=Aktiver/deaktiver HTTP autentisering av brukere med SPNEGO/Kerberos tokens. Informasjonen om autentiserte brukere vil bli klargjort fra denne LDAP-serveren.
+use-kerberos-for-password-authentication=Bruk Kerberos for autentisering av passord
+ldap.use-kerberos-for-password-authentication.tooltip=Bruk Kerberos-innloggingsmodul for \u00E5 autentisere brukernavn/passord mot Kerberos-server i stedet for autentisering mot LDAP-server med Directory Service API
+batch-size=Batch st\u00F8rrelse
+ldap.batch-size.tooltip=Antall LDAP-brukere som vil bli importert fra LDAP til Keycloak innen en enkelt transaksjon.
+ldap.periodic-full-sync.tooltip=Om fullstendig periodisk synkronisering av LDAP-brukere til Keycloak vil v\u00E6re aktivert eller deaktivert.
+ldap.periodic-changed-users-sync.tooltip=Om periodisk synkronisering av endret eller nylig opprettede LDAP-brukere til Keycloak vil v\u00E6re aktivert eller deaktivert.
+ldap.changed-users-sync-period.tooltip=Tidsperiode for synkronisering av endrede eller nylig opprettede LDAP-brukere i sekunder.
+user-federation-mappers=Mappere for brukerfederering
+create-user-federation-mapper=Opprett mapper for brukerfederering
+add-user-federation-mapper=Legg til mapper for brukerfederering
+provider-name=Leverand\u00F8rnavn
+no-user-federation-providers-configured=Ingen leverand\u00F8r for brukerfederering er konfigurert
+no-user-storage-providers-configured=Ingen leverand\u00F8r for brukerlagring er konfigurert
+add-identity-provider=Legg til identitetsleverand\u00F8r
+add-identity-provider-link=Legg til lenke til identitetsleverand\u00F8r
+identity-provider=Identitetsleverand\u00F8r
+identity-provider-user-id=Bruker-ID for identitetsleverand\u00F8r
+identity-provider-user-id.tooltip=Unik ID for brukeren p\u00E5 identitetsleverand\u00F8rens side
+identity-provider-username=Brukernavn til identitetsleverand\u00F8r
+identity-provider-username.tooltip=Brukernavn p\u00E5 identitetsleverand\u00F8rens side
+pagination=Paginering
+
+browser-flow=Nettleserflyt
+browser-flow.tooltip=Velg flyten du \u00F8nsker \u00E5 bruke for nettleser-autentisering.
+registration-flow=Registreringsflyt
+registration-flow.tooltip=Velg flyten du \u00F8nsker for registrering.
+direct-grant-flow=Direct Grant Flyt
+direct-grant-flow.tooltip=Velg flyten du \u00F8nsker \u00E5 bruke for direct grant autentisering.
+reset-credentials=Tilbakestill innloggingsdetaljer
+reset-credentials.tooltip=Velg flyten du \u00F8nsker \u00E5 bruke n\u00E5r brukeren har glemt sine p\u00E5loggingsdetaljer.
+client-authentication=Autentisering av klient
+client-authentication.tooltip=Velg flyten du \u00F8nsker \u00E5 bruke for autentisering av klienter.
+new=Ny
+copy=Kopi
+add-execution=Legg til eksekvering
+add-flow=Legg til flyt
+auth-type=Type auth
+requirement=Krav
+config=Konfig
+no-executions-available=Ingen tilgjengelig eksekvering
+authentication-flows=Autentiseringsflyt
+create-authenticator-config=Opprett konfig for autentikator
+authenticator.alias.tooltip=Navn p\u00E5 konfigurasjonen
+otp-type=Type engangskode
+time-based=Tidsbasert
+counter-based=Tellerbasert
+otp-type.tooltip=Totp er et tidsbasert engangspassord. 'hotp' er et teller basert engangspassord hvor serveren f\u00F8lger med p\u00E5 en teller som den kan hashe mot.
+otp-hash-algorithm=OTP hash-algoritme
+otp-hash-algorithm.tooltip=Hva slags hashing algoritme skal brukes for \u00E5 generere OTP.
+number-of-digits=Antall siffer
+otp.number-of-digits.tooltip=Hvor mange sifre skal OTP ha?
+look-ahead-window=Look Ahead Window
+otp.look-ahead-window.tooltip=Hvor langt frem b\u00F8r serveren se i tilfelle token generator og server er ute av tidssynkronisering eller tellersynkronisering?
+initial-counter=Initiell teller
+otp.initial-counter.tooltip=Hva b\u00F8r den initielle tellerverdien v\u00E6re?
+otp-token-period=Engangskode token
+otp-token-period.tooltip=Hvor mange sekunder burde et engangskode token v\u00E6re gyldig? Standard er satt til 30 sekunder.
+table-of-password-policies=Liste over policy for passord
+add-policy.placeholder=Legg til policy...
+policy-type=Type policy
+policy-value=Verdi for policy
+admin-events=administratorhendelser
+admin-events.tooltip=Viser lagrede administratorhendelser for sikkerhetsdomenet. Hendelser relaterer til administratorkontoen, for eksempel opprettelse av et sikkerhetsdomene. For \u00E5 aktivere persistente hendelser g\u00E5 til konfig.
+login-events=innloggingshendelser
+filter=Filtrer
+update=Oppdater
+reset=Tilbakestill
+operation-types=Operasjonstyper
+resource-types=Ressurstyper
+select-operations.placeholder=Velg operasjoner...
+select-resource-types.placeholder=Velg ressursyper...
+resource-path=Filsti for ressurs
+resource-path.tooltip=Sorter etter filsti for ressurs. St\u00F8tter jokertegn '*' for \u00E5 sjekke om den er lik en del av stien, og '**' for \u00E5 sjekke flere deler. For eksempel 'realms/*/clients/asbc' vil v\u00E6re lik klient-ID asbc i alle sikkerhetsdomener, mens 'realms/master/**' er lik alt i mastersikkerhetsdomenet.
+date-(from)=Dato (Fra)
+date-(to)=Dato (Til)
+authentication-details=Autentiseringsdetaljer
+ip-address=IP-adresse
+time=Tid
+operation-type=Operasjonstype
+resource-type=Ressurstype
+auth=Auth
+representation=Representasjon
+register=Registrer
+required-action=P\u00E5krevd handling
+default-action=Standard handling
+auth.default-action.tooltip=Hvis aktivert, vil enhver ny bruker bli tilordnet denne p\u00E5krevde handlingen.
+no-required-actions-configured=Ingen p\u00E5krevde handlinger er konfigurert
+defaults-to-id=Standardverdi er id
+flows=Flyt
+bindings=Bindinger
+required-actions=P\u00E5krevde handlinger
+password-policy=Passordpolicy
+otp-policy=Policy for engangskode
+user-groups=Brukergruppe
+default-groups=Standardgrupper
+groups.default-groups.tooltip=Sett med grupper som nye brukere automatisk vil bli medlem av.
+cut=Klipp
+paste=Lim inn
+
+create-group=Opprett gruppe
+create-authenticator-execution=Opprett autentiseringsutf\u00F8relse
+create-form-action-execution=Opprett skjema for handlingsutf\u00F8relse
+create-top-level-form=Opprett skjema for toppniv\u00E5
+flow.alias.tooltip=Spesifiserer visningsnavn for flyten.
+top-level-flow-type=Flytstype for toppniv\u00E5
+flow.generic=generisk
+flow.client=klient
+top-level-flow-type.tooltip=Hvilken type toppniv\u00E5 flyt er det? Type 'klient' brukes for autentisering av klienter (applikasjoner) n\u00E5r generisk brukes for brukere og alt annet
+create-execution-flow=Opprett eksekveringsflyt
+flow-type=Type av flyt
+flow.form.type=skjema
+flow-type.tooltip=Hva slags skjema det er
+form-provider=Skjemaleverand\u00F8r
+default-groups.tooltip=Nyopprettede eller registrerte brukere vil automatisk bli lagt til disse gruppene
+select-a-type.placeholder=velg en type
+available-groups=Tilgjengelige grupper
+available-groups.tooltip=Velg en gruppe du \u00F8nsker \u00E5 legge til som standard.
+value=Verdi
+table-of-group-members=Liste over gruppemedlemmer
+last-name=Etternavn
+first-name=Fornavn
+email=E-postadresse
+toggle-navigation=Toggle navigasjon
+manage-account=Administrer konto
+sign-out=Logg ut
+server-info=Serverinformasjon
+resource-not-found=Ressurs <strong>ikke funnet</strong>...
+resource-not-found.instruction=Vi kunne ikke finne ressursen du leter etter. Vennligst kontroller at nettadressen du oppga er riktig.
+go-to-the-home-page=G\u00E5 til hjemmeside &raquo;
+page-not-found=Side <strong>ikke funnet</strong>...
+page-not-found.instruction=Vi kunne ikke finne siden du ser etter. Vennligst kontroller at nettadressen du skrev inn er riktig.
+events.tooltip=Viser lagrede hendelser for sikkerhetsdomenet. Hendelser er relatert til brukerkontoer, for eksempel innlogging av bruker. For \u00E5 aktivere persistente hendelser g\u00E5 til konfig.
+select-event-types.placeholder=Velg hendelsestyper...
+events-config.tooltip=Viser konfigurasjonsalternativer for \u00E5 muliggj\u00F8re persistente bruker- og administratorhendelser.
+select-an-action.placeholder=Velg en handling...
+event-listeners.tooltip=Konfigurer hvilke lyttere som skal motta eventer fra sikkerhetsdomenet.
+login.save-events.tooltip=Hvis aktivert vil innloggingshendelser bli lagret i databasen, noe som gj\u00F8r hendelsene tilgjengelige for administrator og kontoadministrasjonskonsoll.
+clear-events.tooltip=Sletter alle hendelser fra databasen.
+events.expiration.tooltip=Setter utl\u00F8pstid for hendelser. Utl\u00F8pte hendelser vil med jevne mellomrom bli slettet fra databasen.
+admin-events-settings=Innstillinger for administratorhendelser
+save-events=Lagre hendelser
+admin.save-events.tooltip=Hvis aktivert vil administratorhendelser bli lagret i databasen, som vil gj\u00F8re hendelsene tilgjengelige i administrasjonskonsollen.
+saved-types.tooltip=Konfigurer hvilke eventtyper som lagres.
+include-representation=Inkluder representasjon
+include-representation.tooltip=Inkluder JSON-representasjon for \u00E5 skape og oppdatere foresp\u00F8rsler.
+clear-admin-events.tooltip=Sletter alle administratorhendelser i databasen.
+server-version=Serverversjon
+info=Info
+providers=Leverand\u00F8rer
+server-time=Servertid
+server-uptime=Oppetid for server
+memory=Minne
+total-memory=Totalt minne
+free-memory=Ledig minne
+used-memory=Brukt minne
+system=System
+current-working-directory=Gjeldende arbeidskatalog
+java-version=Java versjon
+java-vendor=Java leverand\u00F8r
+java-runtime=Java Runtime
+java-vm=Java VM
+java-vm-version=Java VM versjon
+java-home=Java hjem
+user-name=Brukers navn
+user-timezone=Tidssone for bruker
+user-locale=Lokalitet for bruker
+system-encoding=Systemenkoding
+operating-system=Operativsystem (OS)
+os-architecture=OS arkitektur
+spi=SPI
+granted-roles=Tildelte roller
+granted-protocol-mappers=Innvilgede protokollmappere
+additional-grants=Tillegsrettigheter
+revoke=Opphev
+new-password=Nytt passord
+password-confirmation=Passord bekreftelse
+reset-password=Tilbakestill passord
+credentials.temporary.tooltip=Hvis aktivert, er brukeren p\u00E5krevd til \u00E5 endre passordet ved neste innlogging
+remove-totp=Fjern TOTP
+credentials.remove-totp.tooltip=Fjern generator for engangspassord for bruker.
+reset-actions=Tilbakestill handlinger
+credentials.reset-actions.tooltip=Sett med handlinger som kan utf\u00F8res ved \u00E5 sende en bruker en Tilbakestillingshandling for E-post. 'Verifiser e-post' sender en e-post til brukeren for \u00E5 verifisere e-postadresse. 'Oppdater profil' krever at bruker legger inn personlig informasjon. 'Oppdater passord' krever at bruker skriver inn et nytt passord. 'Konfigurer TOTP' krever installasjon av en passordgenerator for mobil.
+reset-actions-email=Tilbakestillingshandling for E-post.
+send-email=Send e-post
+credentials.reset-actions-email.tooltip=Sender en e-post til en bruker med en lenke. Ved \u00E5 klikke p\u00E5 denne lenken vil brukeren f\u00E5 lov til \u00E5 utf\u00F8re tilbakestillingshandlinger. Brukeren trenger ikke logge inn f\u00F8r dette. For eksempel, sett handlingen for \u00E5 oppdatere passord, klikk p\u00E5 denne knappen, og brukeren vil kunne endre deres passord uten \u00E5 logge inn.
+add-user=Legg til bruker
+created-at=Opprettet ved
+user-enabled=Bruker aktivert
+user-enabled.tooltip=En deaktivert bruker kan ikke logge inn.
+user-temporarily-locked=Bruker er midlertidig l\u00E5st.
+user-temporarily-locked.tooltip=Brukeren kan ha blitt l\u00E5st p\u00E5 grunn av at innloggingsfors\u00F8k har feilet for mange ganger.
+unlock-user=L\u00E5s opp bruker
+federation-link=Federeringslenke
+email-verified=E-post verifisert
+email-verified.tooltip=Har brukerens e-post blitt verifisert?
+required-user-actions=P\u00E5krevde brukerhandlinger
+required-user-actions.tooltip=Krev en handling n\u00E5r brukeren logger inn. 'Verifiser e-post' sender en e-post til brukeren for \u00E5 verifisere deres e-postadresse. 'Oppdater profil' krever at bruker legger inn personlig informasjon. 'Oppdater passord' krever at bruker skriver inn et nytt passord. 'Konfigurer TOTP' krever installasjon av en passordgenerator for mobil.
+locale=Lokalitet
+select-one.placeholder=Velg en...
+impersonate=Utgi deg for \u00E5 v\u00E6re bruker
+impersonate-user=Utgi deg for \u00E5 v\u00E6re bruker
+impersonate-user.tooltip=Logg inn som denne brukeren. Hvis bruker er i samme sikkerhetsdomene som deg, vil din n\u00E5v\u00E6rende innloggede sesjon bli logget ut f\u00F8r du blir logget inn som denne brukeren.
+identity-provider-alias=Alias for identitetsleverand\u00F8r
+provider-user-id=Bruker-ID for leverand\u00F8r
+provider-username=Brukernavn for leverand\u00F8r
+no-identity-provider-links-available=Ingen lenker for identitetsleverand\u00F8r er tilgjengelig
+group-membership=Gruppemedlemskap
+leave=Forlat
+group-membership.tooltip=Gruppen som brukeren er medlem av. Velg en gruppe p\u00E5 listen og klikk p\u00E5 'Forlat' for \u00E5 forlate gruppen.
+membership.available-groups.tooltip=Grupper som brukere kan bli medlem av. Velg en gruppe og klikk p\u00E5 'Bli med' knappen.
+table-of-realm-users=Liste over sikkerhetsdomenebrukere
+view-all-users=Se alle brukere
+unlock-users=L\u00E5s opp brukere
+no-users-available=Ingen brukere tilgjengelig
+users.instruction=Vennligst skriv inn et s\u00F8k, eller klikk p\u00E5 Se alle brukere
+consents=Samtykke
+started=Startet
+logout-all-sessions=Logg ut av alle sesjoner
+logout=Logg ut
+new-name=Nytt navn
+ok=Ok
+attributes=Attributter
+role-mappings=Mapping av roller
+members=Medlemmer
+details=Detaljer
+identity-provider-links=Lenker til identitetsleverand\u00F8r
+register-required-action=Registrer p\u00E5krevd handling
+gender=Kj\u00F8nn
+address=Adresse
+phone=Telefon
+profile-url=Profil URL
+picture-url=Bilde URL
+website=Nettsted
+import-keys-and-cert=Importer n\u00F8kler og sertifikat
+import-keys-and-cert.tooltip=Last opp klientens n\u00F8kkelpar og sertifikat.
+upload-keys=Last opp n\u00F8kler
+download-keys-and-cert=Last ned n\u00F8kler og sertifikat
+no-value-assigned.placeholder=Ingen tilordnet verdi
+remove=Fjern
+no-group-members=Ingen gruppemedlemmer
+temporary=Midlertidig
+join=Bli med
+event-type=Hendelsestype
+events-config=Hendelseskonfigurasjon
+event-listeners=Hendelseslyttere
+login-events-settings=Innstillinger for innloggingshendelser
+clear-events=Fjern hendelser
+saved-types=Lagrede typer
+clear-admin-events=Fjern administratorhendelser
+clear-changes=Fjern endringer
+error=Feil
+
+# Authz
+ # Authz Common
+authz-authorization=Autorisasjon
+authz-owner=Eier
+authz-uri=URI
+authz-scopes=Scope
+authz-resource=Ressurs
+authz-resource-type=Ressurstype
+authz-resources=Ressurser
+authz-scope=Scope
+authz-authz-scopes=Autorisasjonsscopes
+authz-policies=Policier
+authz-permissions=Tillatelser
+authz-evaluate=Evaluer
+authz-icon-uri=Ikon URI
+authz-icon-uri.tooltip=En URI som peker til et ikon.
+authz-select-scope=Velg et scope
+authz-select-resource=Velg en ressurs
+authz-associated-policies=Assosierte policier
+authz-any-resource=Enhver ressurs
+authz-any-scope=Ethvert scope
+authz-any-role=Enhver rolle
+authz-policy-evaluation=Evaluering av policy
+authz-select-client=Velg en klient
+authz-select-user=Velg en bruker
+authz-entitlements=Rettigheter
+authz-no-resources=Ingen ressurser
+authz-result=Resultat
+authz-authorization-services-enabled=Autorisasjon aktivert
+authz-authorization-services-enabled.tooltip=Aktiver/deaktiver finkornet autorisasjonssupport for en klient
+authz-required=P\u00E5krevd
+
+# Authz Settings
+authz-import-config.tooltip=Importer en JSON-fil som inneholder innstillinger for autorisasjon for denne ressursserveren.
+
+authz-policy-enforcement-mode=Modus for h\u00E5ndhevelse av policy
+authz-policy-enforcement-mode.tooltip=Modus for h\u00E5ndhevelse av policy dikterer hvordan policier blir h\u00E5ndhevet n\u00E5r autorisasjonsforesp\u00F8rsler blir evaluert. 'H\u00E5ndhevende' betyr at foresp\u00F8rsler blir nektet som standard selv om det ikke er en policy knyttet til en gitt ressurs. 'Ettergivende' betyr at foresp\u00F8rsler blir tillatt selv om det ikke er en policy knyttet til en gitt ressurs. 'Deaktivert' deaktiverer fullstendig evalueringen av policier og tillater tilgang til enhver ressurs.
+authz-policy-enforcement-mode-enforcing=H\u00E5ndhevende
+authz-policy-enforcement-mode-permissive=Ettergivende
+authz-policy-enforcement-mode-disabled=Deaktivert
+
+authz-remote-resource-management=H\u00E5ndtering av ekstern ressurs
+authz-remote-resource-management.tooltip=Skal ressursene bli h\u00E5ndtert eksternt av ressursserveren? Hvis satt til false kan ressursene kun bli h\u00E5ndtert fra denne administratorkonsollen.
+
+authz-export-settings=Eksporter innstillinger
+authz-export-settings.tooltip=Eksporter og last ned alle innstillinger for autorisasjon for denne ressursserveren.
+
+ # Authz Resource List
+authz-no-resources-available=Ingen tilgjengelige ressurser.
+authz-no-scopes-assigned=Ingen tildelte scopes.
+authz-no-type-defined=Ingen definert type.
+authz-no-permission-assigned=Ingen tillatelse er tildelt.
+authz-no-policy-assigned=Ingen tildelt policy.
+authz-create-permission=Opprett tillatelse
+
+ # Authz Resource Detail
+authz-add-resource=Legg til ressurs
+authz-resource-name.tooltip=Et unikt navn for denne ressursen. Navnet kan bli brukt til \u00E5 identifisere en ressurs og er nyttig i sp\u00F8rringer for en bestemt ressurs.
+authz-resource-owner.tooltip=Eieren av denne ressursen.
+authz-resource-type.tooltip=Ressurstype. Den kan brukes til \u00E5 gruppere ulike ressursinstanser av samme type.
+authz-resource-uri.tooltip=En URI som ogs\u00E5 kan brukes for \u00E5 identifisere denne ressursen.
+authz-resource-scopes.tooltip=Scopes assosiert med denne ressursen.
+
+ # Authz Scope List
+authz-add-scope=Legg til scope
+authz-no-scopes-available=Ingen tilgjengelige scopes.
+
+ # Authz Scope Detail
+authz-scope-name.tooltip=Et unikt navn for dette scopet. Navnet kan bli brukt for \u00E5 identifisere et scope, og er nyttig i sp\u00F8rringer for en bestemt ressurs.
+
+ # Authz Policy List
+authz-all-types=Alle typer
+authz-create-policy=Opprett policy
+authz-no-policies-available=Ingen tilgjengelige policier.
+
+ # Authz Policy Detail
+authz-policy-name.tooltip=Navnet p\u00E5 denne policien.
+authz-policy-description.tooltip=En beskrivelse av denne policien.
+authz-policy-logic=Logikk
+authz-policy-logic-positive=Positiv
+authz-policy-logic-negative=Negativ
+authz-policy-logic.tooltip=Logikken som dikterer hvordan beslutningspolicien skal utf\u00F8rres. Hvis 'Positiv', vil resulterende effekt (tillate eller nekte) oppn\u00E5dd under evalueringen av denne policien bli brukt for \u00E5 ta en beslutning. Hvis 'Negativ', vil resulterende effekt bli opphevet, med andre ord blir en tillatelse til et avslag og motsatt.
+authz-policy-apply-policy=Anvend policy
+authz-policy-apply-policy.tooltip=Spesifiserer alle policies som m\u00E5 bli anvendt for scopes definert av denne policien eller tillatelsen.
+authz-policy-decision-strategy=Beslutningsstrategi
+authz-policy-decision-strategy.tooltip=Beslutningsstrategi som dikterer hvordan policies knyttet til en gitt policy blir evaluert og hvordan endelig avgj\u00F8relse oppn\u00E5s. 'Bekreftende' betyr at minst en policy m\u00E5 evalueres til en positiv beslutning for at den samlede avgj\u00F8relsen kan bli positiv. 'Enstemmig' betyr at alle policies m\u00E5 evalueres til en positiv beslutning for at den samlede avgj\u00F8relsen kan bli positiv. 'Konsensus' betyr at antall positive beslutninger m\u00E5 v\u00E6re h\u00F8yere enn antall negative beslutninger. Hvis antallet av positive og negative er likt, blir den samlede avgj\u00F8relsen negativ.
+authz-policy-decision-strategy-affirmative=Bekreftende
+authz-policy-decision-strategy-unanimous=Enstemmig
+authz-policy-decision-strategy-consensus=Konsensus
+authz-select-a-policy=Velg en policy
+
+ # Authz Role Policy Detail
+authz-add-role-policy=Legg til policy for rolle
+authz-no-roles-assigned=Ingen tildelte roller.
+authz-policy-role-roles.tooltip=Spesifiser sikkerhetsdomenerolle(r) som tillates av denne policien.
+authz-policy-role-clients.tooltip=Velger en klient for \u00E5 filtrere klientroller som kan bli tatt i bruk av denne policien.
+authz-policy-role-client-roles.tooltip=Spesifiserer klientroller tillatt av denne policien.
+
+  # Authz User Policy Detail
+authz-add-user-policy=Legg til policy for bruker
+authz-no-users-assigned=Ingen tildelte brukere.
+authz-policy-user-users.tooltip=Spesifiser bruker(e) som tillates av denne policien.
+
+ # Authz Time Policy Detail
+authz-add-time-policy=Legg til policy for tid
+authz-policy-time-not-before.tooltip=Definerer tiden f\u00F8r policien M\u00C5 IKKE innvilges. Denne innvilges kun om gjeldende dato/tid er f\u00F8r eller lik denne verdien.
+authz-policy-time-not-on-after=Ikke p\u00E5 eller etter
+authz-policy-time-not-on-after.tooltip=Definerer tiden etter en policy M\u00C5 IKKE innvilges. Denne innvilges kun om gjeldende dato/tid er f\u00F8r eller lik denne verdien.
+
+ # Authz Drools Policy Detail
+authz-add-drools-policy=Legg til Drools policy
+authz-policy-drools-maven-artifact-resolve=L\u00F8s
+authz-policy-drools-maven-artifact=Policy for Maven artefakt.
+authz-policy-drools-maven-artifact.tooltip=Et Maven GAV som peker til et artefakt hvor reglene vil bli lastet fra. Med en gang du har gitt GAV kan du klikke *L\u00F8s* for \u00E5 laste felter for b\u00E5de *Modul* og *Sesjon*
+authz-policy-drools-module=Modul
+authz-policy-drools-module.tooltip=Modulen som brukes av denne policien. Du m\u00E5 oppgi en modul for \u00E5 velge en bestemt \u00F8kt der reglene vil bli lastet fra.
+authz-policy-drools-session=Sesjon
+authz-policy-drools-session.tooltip=Sesjonen brukt av denne policien. Sesjonen vil gi alle regler for evaluering ved prosessering av policien.
+authz-policy-drools-update-period=Oppdater periode
+authz-policy-drools-update-period.tooltip=Spesifiserer et intervall for \u00E5 skanne etter oppdateringer for artefakter.
+
+ # Authz JS Policy Detail
+authz-add-js-policy=Legg til policy for JavaScript
+authz-policy-js-code=Kode
+authz-policy-js-code.tooltip=JavaScript-koden angir betingelsene for denne politikken.
+
+
+ # Authz Aggregated Policy Detail
+authz-aggregated=Aggregert
+authz-add-aggregated-policy=Legg til policy for aggregering.
+
+ # Authz Permission List
+authz-no-permissions-available=Ingen tilgjengelige tillatelser.
+
+ # Authz Permission Detail
+authz-permission-name.tooltip=Navnet p\u00E5 denne tillatelsen.
+authz-permission-description.tooltip=En beskrivelse av denne tillatelsen.
+
+ # Authz Resource Permission Detail
+authz-add-resource-permission=Legg til tillatelse for ressurs.
+authz-permission-resource-apply-to-resource-type=Bruk p\u00E5 ressurstype
+authz-permission-resource-apply-to-resource-type.tooltip=Spesifiserer om denne tillatelsen skal gjelde for alle ressurser med en gitt type. I dette tilfellet vil tillatelsen bli evaluert for alle instanser av gitt ressurstype.
+authz-permission-resource-resource.tooltip=Spesifiserer at denne tillatelsen m\u00E5 bli brukt for en spesifikk ressursinstans.
+authz-permission-resource-type.tooltip=Spesifiserer at denne tillatelsen m\u00E5 bli anvendt for alle ressursinstanser for en gitt type.
+
+ # Authz Scope Permission Detail
+authz-add-scope-permission=Legg til tillatelse for scope
+authz-permission-scope-resource.tooltip=Begrens scopes til de som er tilknyttet den valgte ressursen. Hvis dette ikke er valgt vil alle scopes v\u00E6re tilgjengelige.
+authz-permission-scope-scope.tooltip=Spesifiserer at denne tillatelse m\u00E5 anvendes p\u00E5 en eller flere scopes.
+
+ # Authz Evaluation
+authz-evaluation-identity-information=Identitetsinformasjon
+authz-evaluation-identity-information.tooltip=De tilgjengelige alternativene for \u00E5 konfigurere identitesinformasjon som vil bli brukt ved evaluering av policier.
+authz-evaluation-client.tooltip=Velg klienten som vil utf\u00F8re denne autorisasjonsforesp\u00F8rselen.
+authz-evaluation-user.tooltip=Velg en bruker hvis identitet vil bli brukt for \u00E5 s\u00F8ke tillatelser fra serveren.
+authz-evaluation-role.tooltip=Velg en rolle som du vil knytte til den valgte brukeren.
+authz-evaluation-new=Ny evaluering
+authz-evaluation-re-evaluate=Re-evaluering
+authz-evaluation-previous=Forrige evaluering
+authz-evaluation-contextual-info=Kontekstuell informasjon
+authz-evaluation-contextual-info.tooltip=Tilgjengelige valg for \u00E5 konfigurere enhver kontekstuell informasjon som vil bli brukt ved evaluering av policier.
+authz-evaluation-contextual-attributes=Kontekstuelle attributter
+authz-evaluation-contextual-attributes.tooltip=Ethvert attributt gitt av et kj\u00F8rende milj\u00F8 eller ved utf\u00F8relseskontekst.
+authz-evaluation-permissions.tooltip=De tilgjengelige alternativene for \u00E5 konfigurere tillatelsene for hvilke policies som skal anvendes.
+authz-evaluation-evaluate=Evaluer
+authz-evaluation-any-resource-with-scopes=Enhver ressurs med scope(s)
+authz-evaluation-no-result=Kunne ikke f\u00E5 et resultat for den gitte autorisasjonsforesp\u00F8rselen. Sjekk om de tilgjengelige ressursene er tilknyttet en policy.
+authz-evaluation-no-policies-resource=Ingen policies ble funnet for denne ressursen.
+authz-evaluation-result.tooltip=Det samlede resultatet for denne foresp\u00F8rselen for tillatelse.
+authz-evaluation-scopes.tooltip=Liste over tillatte scopes.
+authz-evaluation-policies.tooltip=Detaljer om hvilke policies som ble evaluert og deres avgj\u00F8relser.
+authz-evaluation-authorization-data=Respons
+authz-evaluation-authorization-data.tooltip=Representerer et token som b\u00E6rer autorisasjonsdata som et resultat av prosesseringen av en autorisasjonsforesp\u00F8rsel. Denne representasjonen er hva Keycloak sender ut til klienter som ettersp\u00F8r tillatelser. Sjekk autorisasjonsclaim for tillatelsene som ble gitt basert p\u00E5 n\u00E5v\u00E6rende autorisasjonsforesp\u00F8rsel.
+authz-show-authorization-data=Vis autorisasjonsdata
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_ru.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_ru.properties
index c28da56..6a59cc9 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_ru.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_ru.properties
@@ -233,8 +233,8 @@ assertion-consumer-post-binding-url=\u0421\u0432\u044F\u0437\u044B\u0432\u0430\u
 assertion-consumer-post-binding-url.tooltip=SAML POST \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 URL \u0434\u043B\u044F \u043A\u043B\u0438\u0435\u043D\u0442\u0441\u043A\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043E\u0432 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u044F (\u0437\u0430\u043F\u0440\u043E\u0441\u044B \u0432\u0445\u043E\u0434\u0430). \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u044D\u0442\u043E \u043F\u043E\u043B\u0435 \u043F\u0443\u0441\u0442\u044B\u043C, \u0435\u0441\u043B\u0438 \u043D\u0435 \u0438\u043C\u0435\u0435\u0442\u0435 URL \u0434\u043B\u044F \u043E\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043B\u0435\u043D\u0438\u044F \u0442\u0430\u043A\u043E\u0439 \u0441\u0432\u044F\u0437\u043A\u0438.
 assertion-consumer-redirect-binding-url=\u0421\u0432\u044F\u0437\u044B\u0432\u0430\u043D\u0438\u0435 URL \u043F\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043E\u043C \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u044F
 assertion-consumer-redirect-binding-url.tooltip=SAML \u043F\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044F \u043D\u0430 \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 URL \u0434\u043B\u044F \u043A\u043B\u0438\u0435\u043D\u0442\u0441\u043A\u043E\u0433\u043E \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u043D\u043E\u0433\u043E \u043F\u043E\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043B\u044F (\u0437\u0430\u043F\u0440\u043E\u0441\u044B \u0432\u0445\u043E\u0434\u0430). \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u044D\u0442\u043E \u043F\u043E\u043B\u0435 \u043F\u0443\u0441\u0442\u044B\u043C, \u0435\u0441\u043B\u0438 \u0432\u044B \u043D\u0435 \u0438\u043C\u0435\u0435\u0442\u0435 URL \u0434\u043B\u044F \u0442\u0430\u043A\u043E\u0433\u043E \u0441\u0432\u044F\u0437\u044B\u0432\u0430\u043D\u0438\u044F.
-logout-service-binding-post-url=\u0421\u0432\u044F\u0437\u044B\u0432\u0430\u043D\u0438\u0435 URL \u0434\u043B\u044F \u0432\u044B\u0445\u043E\u0434\u0430 \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043B\u044F POST-\u043C\u0435\u0442\u043E\u0434\u0430
-logout-service-binding-post-url.tooltip=SAML POST \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 URL \u0434\u043B\u044F \u043A\u043B\u0438\u0435\u043D\u0442\u0441\u043A\u043E\u0433\u043E \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0435\u0434\u0438\u043D\u043E\u0433\u043E \u0432\u044B\u0445\u043E\u0434\u0430. \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u044D\u0442\u043E \u043F\u043E\u043B\u0435 \u043F\u0443\u0441\u0442\u044B\u043C, \u0435\u0441\u043B\u0438 \u0432\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0435 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u044B\u0435 \u0441\u0432\u044F\u0437\u0438
+logout-service-post-binding-url=\u0421\u0432\u044F\u0437\u044B\u0432\u0430\u043D\u0438\u0435 URL \u0434\u043B\u044F \u0432\u044B\u0445\u043E\u0434\u0430 \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043B\u044F POST-\u043C\u0435\u0442\u043E\u0434\u0430
+logout-service-post-binding-url.tooltip=SAML POST \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 URL \u0434\u043B\u044F \u043A\u043B\u0438\u0435\u043D\u0442\u0441\u043A\u043E\u0433\u043E \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0435\u0434\u0438\u043D\u043E\u0433\u043E \u0432\u044B\u0445\u043E\u0434\u0430. \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u044D\u0442\u043E \u043F\u043E\u043B\u0435 \u043F\u0443\u0441\u0442\u044B\u043C, \u0435\u0441\u043B\u0438 \u0432\u044B \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0435 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u044B\u0435 \u0441\u0432\u044F\u0437\u0438
 logout-service-redir-binding-url=\u0421\u0432\u044F\u0437\u044B\u0432\u0430\u043D\u0438\u0435 URL \u043F\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u0438 \u0434\u043B\u044F \u0432\u044B\u0445\u043E\u0434\u0430 \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430
 logout-service-redir-binding-url.tooltip=SAML \u043F\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u0443\u0435\u0442 \u043D\u0430 \u0441\u0432\u044F\u0437\u0430\u043D\u043D\u044B\u0439 URL \u0434\u043B\u044F \u0435\u0434\u0438\u043D\u043E\u0439 \u0442\u043E\u0447\u043A\u0438 \u0432\u044B\u0445\u043E\u0434\u0430 \u0438\u0437 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0434\u043B\u044F \u043A\u043B\u0438\u0435\u043D\u0442\u043E\u0432. \u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u044D\u0442\u043E \u043F\u043E\u043B\u0435 \u043F\u0443\u0441\u0442\u044B\u043C, \u0435\u0441\u043B\u0438 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0435 \u0440\u0430\u0437\u043B\u0438\u0447\u043D\u044B\u0435 \u0441\u0432\u044F\u0437\u0438.
 
diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/messages_en.properties
index 95e16db..345cb25 100644
--- a/themes/src/main/resources/theme/base/admin/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/messages_en.properties
@@ -12,3 +12,6 @@ ldapErrorMissingClientId=Client ID needs to be provided in config when Realm Rol
 ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=Not possible to preserve group inheritance and use UID membership type together.
 ldapErrorCantWriteOnlyForReadOnlyLdap=Can't set write only when LDAP provider mode is not WRITABLE
 ldapErrorCantWriteOnlyAndReadOnly=Can't set write-only and read-only together
+
+clientRedirectURIsFragmentError=Redirect URIs must not contain an URI fragment
+clientRootURLFragmentError=Root URL must not contain an URL fragment
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_ja.properties b/themes/src/main/resources/theme/base/admin/messages/messages_ja.properties
new file mode 100644
index 0000000..9a8d26d
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/messages/messages_ja.properties
@@ -0,0 +1,15 @@
+# encoding: utf-8
+invalidPasswordMinLengthMessage=無効なパスワード: 最小 {0} の長さが必要です。
+invalidPasswordMinLowerCaseCharsMessage=無効なパスワード: 少なくとも {0} 文字の小文字を含む必要があります。
+invalidPasswordMinDigitsMessage=無効なパスワード: 少なくとも {0} 文字の数字を含む必要があります。
+invalidPasswordMinUpperCaseCharsMessage=無効なパスワード: 少なくとも {0} 文字の大文字を含む必要があります。
+invalidPasswordMinSpecialCharsMessage=無効なパスワード:  少なくとも {0} 文字の特殊文字を含む必要があります。
+invalidPasswordNotUsernameMessage=無効なパスワード: ユーザー名と同じパスワードは禁止されています。
+invalidPasswordRegexPatternMessage=無効なパスワード: 正規表現パターンと一致しません。
+invalidPasswordHistoryMessage=無効なパスワード: 最近の {0} パスワードのいずれかと同じパスワードは禁止されています。
+
+ldapErrorInvalidCustomFilter=LDAP フィルターのカスタム設定が、 「(」 から開始または 「)」 で終了となっていません。
+ldapErrorMissingClientId=レルムロールマッピングを使用しない場合は、クライアント ID は設定内で提供される必要があります。
+ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=グループ継承と UID メンバーシップタイプを一緒に保存することはできません。
+ldapErrorCantWriteOnlyForReadOnlyLdap=LDAP プロバイダーモードが WRITABLE ではない場合は、write only を設定することはできません。
+ldapErrorCantWriteOnlyAndReadOnly=write-only と read-only を一緒に設定することはできません。
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/admin/messages/messages_no.properties b/themes/src/main/resources/theme/base/admin/messages/messages_no.properties
new file mode 100644
index 0000000..43cb61d
--- /dev/null
+++ b/themes/src/main/resources/theme/base/admin/messages/messages_no.properties
@@ -0,0 +1,14 @@
+invalidPasswordMinLengthMessage=Ugyldig passord: minimum lengde {0}.
+invalidPasswordMinLowerCaseCharsMessage=Ugyldig passord: m\u00E5 inneholde minst {0} sm\u00E5 bokstaver.
+invalidPasswordMinDigitsMessage=Ugyldig passord: m\u00E5 inneholde minst {0} sifre.
+invalidPasswordMinUpperCaseCharsMessage=Ugyldig passord: m\u00E5 inneholde minst {0} store bokstaver.
+invalidPasswordMinSpecialCharsMessage=Ugyldig passord: m\u00E5 inneholde minst {0} spesialtegn.
+invalidPasswordNotUsernameMessage=Ugyldig passord: kan ikke v\u00E6re likt brukernavn.
+invalidPasswordRegexPatternMessage=Ugyldig passord: tilfredsstiller ikke kravene for passord-m\u00F8nster.
+invalidPasswordHistoryMessage=Ugyldig passord: kan ikke v\u00E6re likt noen av de {0} foreg\u00E5ende passordene.
+
+ldapErrorInvalidCustomFilter=Tilpasset konfigurasjon av LDAP-filter starter ikke med "(" eller slutter ikke med ")".
+ldapErrorMissingClientId=KlientID m\u00E5 v\u00E6re tilgjengelig i config n\u00E5r sikkerhetsdomenerollemapping ikke brukes.
+ldapErrorCantPreserveGroupInheritanceWithUIDMembershipType=Ikke mulig \u00E5 bevare gruppearv og samtidig bruke UID medlemskapstype.
+ldapErrorCantWriteOnlyForReadOnlyLdap=Kan ikke sette write-only n\u00E5r LDAP leverand\u00F8r-modus ikke er WRITABLE
+ldapErrorCantWriteOnlyAndReadOnly=Kan ikke sette b\u00E5de write-only og read-only
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index ec37854..72b6c43 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -83,6 +83,13 @@ module.controller('ResourceServerResourceCtrl', function($scope, $http, $route, 
     $scope.realm = realm;
     $scope.client = client;
 
+    $scope.query = {
+        realm: realm.realm,
+        client : client.id,
+        max : 20,
+        first : 0
+    };
+
     ResourceServer.get({
         realm : $route.current.params.realm,
         client : client.id
@@ -93,10 +100,35 @@ module.controller('ResourceServerResourceCtrl', function($scope, $http, $route, 
             $location.path('/realms/' + $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/permission/resource/create').search({rsrid: resource._id});
         }
 
-        ResourceServerResource.query({realm : realm.realm, client : client.id}, function (data) {
-            $scope.resources = data;
-        });
+        $scope.searchQuery();
     });
+
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.searchQuery();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.searchQuery();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.searchQuery();
+    }
+
+    $scope.searchQuery = function() {
+        $scope.searchLoaded = false;
+
+        $scope.resources = ResourceServerResource.query($scope.query, function() {
+            $scope.searchLoaded = true;
+            $scope.lastSearch = $scope.query.search;
+        });
+    };
 });
 
 module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $route, $location, realm, ResourceServer, client, ResourceServerResource, ResourceServerScope, AuthzDialog, Notifications) {
@@ -234,20 +266,52 @@ module.controller('ResourceServerScopeCtrl', function($scope, $http, $route, $lo
     $scope.realm = realm;
     $scope.client = client;
 
+    $scope.query = {
+        realm: realm.realm,
+        client : client.id,
+        max : 20,
+        first : 0
+    };
+
     ResourceServer.get({
         realm : $route.current.params.realm,
         client : client.id
     }, function(data) {
         $scope.server = data;
 
-        ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
-            $scope.scopes = data;
-        });
-
         $scope.createPolicy = function(scope) {
             $location.path('/realms/' + $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/permission/scope/create').search({scpid: scope.id});
         }
+
+        $scope.searchQuery();
     });
+
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.searchQuery();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.searchQuery();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.searchQuery();
+    }
+
+    $scope.searchQuery = function() {
+        $scope.searchLoaded = false;
+
+        $scope.scopes = ResourceServerScope.query($scope.query, function() {
+            $scope.searchLoaded = true;
+            $scope.lastSearch = $scope.query.search;
+        });
+    };
 });
 
 module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $route, $location, realm, ResourceServer, client, ResourceServerScope, AuthzDialog, Notifications) {
@@ -364,6 +428,14 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
     $scope.client = client;
     $scope.policyProviders = [];
 
+    $scope.query = {
+        realm: realm.realm,
+        client : client.id,
+        permission: false,
+        max : 20,
+        first : 0
+    };
+
     PolicyProvider.query({
         realm : $route.current.params.realm,
         client : client.id
@@ -380,8 +452,35 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
         client : client.id
     }, function(data) {
         $scope.server = data;
+        $scope.searchQuery();
+    });
+
+    $scope.addPolicy = function(policyType) {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + policyType.type + "/create");
+    }
+
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.searchQuery();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.searchQuery();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.searchQuery();
+    }
+
+    $scope.searchQuery = function() {
+        $scope.searchLoaded = false;
 
-        ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
+        ResourceServerPolicy.query($scope.query, function(data) {
             $scope.policies = [];
 
             for (i = 0; i < data.length; i++) {
@@ -389,12 +488,11 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
                     $scope.policies.push(data[i]);
                 }
             }
-        });
-    });
 
-    $scope.addPolicy = function(policyType) {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + policyType.type + "/create");
-    }
+            $scope.searchLoaded = true;
+            $scope.lastSearch = $scope.query.search;
+        });
+    };
 });
 
 module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route, $location, realm, ResourceServer, ResourceServerPolicy, PolicyProvider, client) {
@@ -402,6 +500,14 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
     $scope.client = client;
     $scope.policyProviders = [];
 
+    $scope.query = {
+        realm: realm.realm,
+        client : client.id,
+        permission: true,
+        max : 20,
+        first : 0
+    };
+
     PolicyProvider.query({
         realm : $route.current.params.realm,
         client : client.id
@@ -418,8 +524,35 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
         client : client.id
     }, function(data) {
         $scope.server = data;
+        $scope.searchQuery();
+    });
+
+    $scope.addPolicy = function(policyType) {
+        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + policyType.type + "/create");
+    }
+
+    $scope.firstPage = function() {
+        $scope.query.first = 0;
+        $scope.searchQuery();
+    }
+
+    $scope.previousPage = function() {
+        $scope.query.first -= parseInt($scope.query.max);
+        if ($scope.query.first < 0) {
+            $scope.query.first = 0;
+        }
+        $scope.searchQuery();
+    }
+
+    $scope.nextPage = function() {
+        $scope.query.first += parseInt($scope.query.max);
+        $scope.searchQuery();
+    }
+
+    $scope.searchQuery = function() {
+        $scope.searchLoaded = false;
 
-        ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
+        ResourceServerPolicy.query($scope.query, function(data) {
             $scope.policies = [];
 
             for (i = 0; i < data.length; i++) {
@@ -427,12 +560,11 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
                     $scope.policies.push(data[i]);
                 }
             }
-        });
-    });
 
-    $scope.addPolicy = function(policyType) {
-        $location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + policyType.type + "/create");
-    }
+            $scope.searchLoaded = true;
+            $scope.lastSearch = $scope.query.search;
+        });
+    };
 });
 
 module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http, $route, realm, client, PolicyController) {
@@ -958,7 +1090,36 @@ module.controller('ResourceServerPolicyTimeDetailCtrl', function($scope, $route,
         },
 
         onInitUpdate : function(policy) {
-
+            if (policy.config.dayMonth) {
+                policy.config.dayMonth = parseInt(policy.config.dayMonth);
+            }
+            if (policy.config.dayMonthEnd) {
+                policy.config.dayMonthEnd = parseInt(policy.config.dayMonthEnd);
+            }
+            if (policy.config.month) {
+                policy.config.month = parseInt(policy.config.month);
+            }
+            if (policy.config.monthEnd) {
+                policy.config.monthEnd = parseInt(policy.config.monthEnd);
+            }
+            if (policy.config.year) {
+                policy.config.year = parseInt(policy.config.year);
+            }
+            if (policy.config.yearEnd) {
+                policy.config.yearEnd = parseInt(policy.config.yearEnd);
+            }
+            if (policy.config.hour) {
+                policy.config.hour = parseInt(policy.config.hour);
+            }
+            if (policy.config.hourEnd) {
+                policy.config.hourEnd = parseInt(policy.config.hourEnd);
+            }
+            if (policy.config.minute) {
+                policy.config.minute = parseInt(policy.config.minute);
+            }
+            if (policy.config.minuteEnd) {
+                policy.config.minuteEnd = parseInt(policy.config.minuteEnd);
+            }
         },
 
         onUpdate : function() {
@@ -974,6 +1135,19 @@ module.controller('ResourceServerPolicyTimeDetailCtrl', function($scope, $route,
 
         }
     }, realm, client, $scope);
+
+    $scope.isRequired = function () {
+        var policy = $scope.policy;
+        if (policy.config.noa || policy.config.nbf
+            || policy.config.dayMonth
+            || policy.config.month
+            || policy.config.year
+            || policy.config.hour
+            || policy.config.minute) {
+            return false;
+        }
+        return true;
+    }
 });
 
 module.controller('ResourceServerPolicyAggregateDetailCtrl', function($scope, $route, $location, realm, PolicyController, ResourceServerPolicy, client) {
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index d1041c7..3bbd471 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -365,11 +365,12 @@ module.controller('ClientCertificateImportCtrl', function($scope, $location, $ht
     ];
 
     if (callingContext == 'jwt-credentials') {
-        $scope.keyFormats.push('JSON Web Key Set (JWK)');
+        $scope.keyFormats.push('Public Key PEM');
+        $scope.keyFormats.push('JSON Web Key Set');
     }
 
     $scope.hideKeystoreSettings = function() {
-        return $scope.uploadKeyFormat == 'Certificate PEM' || $scope.uploadKeyFormat == 'JSON Web Key Set (JWK)';
+        return $scope.uploadKeyFormat == 'Certificate PEM' || $scope.uploadKeyFormat == 'Public Key PEM' || $scope.uploadKeyFormat == 'JSON Web Key Set';
     }
 
     $scope.uploadKeyFormat = $scope.keyFormats[0];
@@ -791,6 +792,17 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
         {name: "INCLUSIVE_WITH_COMMENTS", value: "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"}
     ];
 
+    $scope.oidcSignatureAlgorithms = [
+        "unsigned",
+        "RS256"
+    ];
+
+    $scope.requestObjectSignatureAlgorithms = [
+        "any",
+        "none",
+        "RS256"
+    ];
+
     $scope.realm = realm;
     $scope.samlAuthnStatement = false;
     $scope.samlMultiValuedRoles = false;
@@ -891,6 +903,12 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
                 $scope.samlForcePostBinding = false;
             }
         }
+
+        var attrVal1 = $scope.client.attributes['user.info.response.signature.alg'];
+        $scope.userInfoSignedResponseAlg = attrVal1==null ? 'unsigned' : attrVal1;
+
+        var attrVal2 = $scope.client.attributes['request.object.signature.alg'];
+         $scope.requestObjectSignatureAlg = attrVal2==null ? 'any' : attrVal2;
     }
 
     if (!$scope.create) {
@@ -955,6 +973,22 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
         $scope.client.attributes['saml_name_id_format'] = $scope.nameIdFormat;
     };
 
+    $scope.changeUserInfoSignedResponseAlg = function() {
+        if ($scope.userInfoSignedResponseAlg === 'unsigned') {
+            $scope.client.attributes['user.info.response.signature.alg'] = null;
+        } else {
+            $scope.client.attributes['user.info.response.signature.alg'] = $scope.userInfoSignedResponseAlg;
+        }
+    };
+
+    $scope.changeRequestObjectSignatureAlg = function() {
+        if ($scope.requestObjectSignatureAlg === 'any') {
+            $scope.client.attributes['request.object.signature.alg'] = null;
+        } else {
+            $scope.client.attributes['request.object.signature.alg'] = $scope.requestObjectSignatureAlg;
+        }
+    };
+
     $scope.$watch(function() {
         return $location.path();
     }, function() {
@@ -1084,6 +1118,12 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
             }, $scope.client, function() {
                 $route.reload();
                 Notifications.success("Your changes have been saved to the client.");
+            }, function(error) {
+                if (error.status == 400 && error.data.error_description) {
+                    Notifications.error(error.data.error_description);
+                } else {
+                    Notifications.error('Unexpected error when updating client');
+                }
             });
         }
     };
@@ -1198,6 +1238,12 @@ module.controller('CreateClientCtrl', function($scope, realm, client, templates,
             var id = l.substring(l.lastIndexOf("/") + 1);
             $location.url("/realms/" + realm.realm + "/clients/" + id);
             Notifications.success("The client has been created.");
+        }, function(error) {
+            if (error.status == 400 && error.data.error_description) {
+                Notifications.error(error.data.error_description);
+            } else {
+                Notifications.error('Unexpected error when creating client');
+            }
         });
     };
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
index a41fe18..bfd1b22 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/permission/resource-server-permission-list.html
@@ -10,12 +10,21 @@
                         <div class="form-group">
                             {{:: 'filter' | translate}}:&nbsp;&nbsp;
                             <div class="input-group">
-                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
+                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" id="policySearch" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
                             </div>
                             <div class="input-group">
-                                <select class="form-control search" data-ng-model="search.type"
-                                        ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type">
-                                    <option value="" selected ng-click="search.type = ''">{{:: 'authz-all-types' | translate}}</option>
+                                <input type="text" placeholder="{{:: 'authz-resource' | translate}}" data-ng-model="query.resource" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
+                            </div>
+                            <div class="input-group">
+                                <select class="form-control search" data-ng-model="query.type"
+                                        ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type" data-ng-change="firstPage()">
+                                    <option value="" selected ng-click="query.type = ''">{{:: 'authz-all-types' | translate}}</option>
                                 </select>
                             </div>
                         </div>
@@ -36,6 +45,17 @@
                 <th>{{:: 'authz-associated-policies' | translate}}</th>
             </tr>
         </thead>
+        <tfoot data-ng-show="policies && (policies.length >= query.max || query.first > 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
         <tbody>
             <tr ng-repeat="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a></td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html
index a121f17..ba53e0b 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-drools-detail.html
@@ -88,10 +88,10 @@
                     <select class="form-control" name="policy.config.scannerPeriodUnit"
                             data-ng-model="policy.config.scannerPeriodUnit"
                             ng-disabled="!policy.config.sessionName">
-                        <option>{{:: 'seconds' | translate}}</option>
-                        <option>{{:: 'minutes' | translate}}</option>
-                        <option>{{:: 'hours' | translate}}</option>
-                        <option>{{:: 'days' | translate}}</option>
+                        <option value="Seconds">{{:: 'seconds' | translate}}</option>
+                        <option value="Minutes">{{:: 'minutes' | translate}}</option>
+                        <option value="Hours">{{:: 'hours' | translate}}</option>
+                        <option value="Days">{{:: 'days' | translate}}</option>
                     </select>
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-drools-update-period.tooltip' | translate}}</kc-tooltip>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
index fc4af74..5177734 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
@@ -37,7 +37,7 @@
                 <label class="col-md-2 control-label" for="policy.config.nbf">{{:: 'not-before' | translate}}</label>
 
                 <div class="col-md-6 time-selector">
-                    <input class="form-control" style="width: 150px" type="text" id="policy.config.nbf" name="notBefore" data-ng-model="policy.config.nbf" placeholder="yyyy-MM-dd hh:mm:ss">
+                    <input class="form-control" style="width: 150px" type="text" id="policy.config.nbf" name="notBefore" data-ng-model="policy.config.nbf" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-time-not-before.tooltip' | translate}}</kc-tooltip>
             </div>
@@ -45,10 +45,50 @@
                 <label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-not-on-after' | translate}}</label>
 
                 <div class="col-md-6 time-selector">
-                    <input class="form-control" style="width: 150px" type="text" id="policy.config.noa" name="policy.config.noa" data-ng-model="policy.config.noa" placeholder="yyyy-MM-dd hh:mm:ss">
+                    <input class="form-control" style="width: 150px" type="text" id="policy.config.noa" name="policy.config.noa" data-ng-model="policy.config.noa" placeholder="yyyy-MM-dd hh:mm:ss" data-ng-required="isRequired()">
                 </div>
                 <kc-tooltip>{{:: 'authz-policy-time-not-on-after.tooltip' | translate}}</kc-tooltip>
             </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-day-month' | translate}}</label>
+
+                <div class="col-md-6 time-selector">
+                    <input class="form-control" type="number" min="1" max="31" data-ng-model="policy.config.dayMonth" id="dayMonth" name="dayMonth" data-ng-required="isRequired()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<input class="form-control" type="number" min="{{policy.config.dayMonth}}" max="31" data-ng-model="policy.config.dayMonthEnd" id="dayMonthEnd" name="dayMonthEnd"/>
+                </div>
+                <kc-tooltip>{{:: 'authz-policy-time-day-month.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-month' | translate}}</label>
+
+                <div class="col-md-6 time-selector">
+                    <input class="form-control" type="number" min="1" max="12" data-ng-model="policy.config.month" id="month" name="month" data-ng-required="isRequired()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<input class="form-control" type="number" min="{{policy.config.month}}" max="12" data-ng-model="policy.config.monthEnd" id="monthEnd" name="monthEnd"/>
+                </div>
+                <kc-tooltip>{{:: 'authz-policy-time-month.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-year' | translate}}</label>
+
+                <div class="col-md-6 time-selector">
+                    <input class="form-control" type="number" min="2016" max="2050" data-ng-model="policy.config.year" id="year" name="year" data-ng-required="isRequired()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<input class="form-control" type="number" min="{{policy.config.year}}" max="2050" data-ng-model="policy.config.yearEnd" id="yearEnd" name="yearEnd"/>
+                </div>
+                <kc-tooltip>{{:: 'authz-policy-time-year.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-hour' | translate}}</label>
+
+                <div class="col-md-6 time-selector">
+                    <input class="form-control" type="number" min="0" max="23" data-ng-model="policy.config.hour" id="hour" name="hour" data-ng-required="isRequired()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<input class="form-control" type="number" min="{{policy.config.hour}}" max="23" data-ng-model="policy.config.hourEnd" id="hourEnd" name="hourEnd"/>
+                </div>
+                <kc-tooltip>{{:: 'authz-policy-time-hour.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group">
+                <label class="col-md-2 control-label" for="policy.config.noa">{{:: 'authz-policy-time-minute' | translate}}</label>
+
+                <div class="col-md-6 time-selector">
+                    <input class="form-control" type="number" min="0" max="59" data-ng-model="policy.config.minute" id="minute" name="minute" data-ng-required="isRequired()"/>&nbsp;&nbsp;to&nbsp;&nbsp;<input class="form-control" type="number" min="{{policy.config.minute}}" max="59" data-ng-model="policy.config.minuteEnd" id="minuteEnd" name="minuteEnd"/>
+                </div>
+                <kc-tooltip>{{:: 'authz-policy-time-minute.tooltip' | translate}}</kc-tooltip>
+            </div>
             <div class="form-group clearfix">
                 <label class="col-md-2 control-label" for="policy.logic">{{:: 'authz-policy-logic' | translate}}</label>
 
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
index 34240b6..84600c0 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/resource-server-policy-list.html
@@ -10,12 +10,21 @@
                         <div class="form-group">
                             {{:: 'filter' | translate}}:&nbsp;&nbsp;
                             <div class="input-group">
-                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
+                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" id="policySearch" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
                             </div>
                             <div class="input-group">
-                                <select class="form-control search" data-ng-model="search.type"
-                                        ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type">
-                                    <option value="" selected ng-click="search.type = ''">{{:: 'authz-all-types' | translate}}</option>
+                                <input type="text" placeholder="{{:: 'authz-resource' | translate}}" data-ng-model="query.resource" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
+                            </div>
+                            <div class="input-group">
+                                <select class="form-control search" data-ng-model="query.type"
+                                        ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type" data-ng-change="firstPage()">
+                                    <option value="" selected ng-click="query.type = ''">{{:: 'authz-all-types' | translate}}</option>
                                 </select>
                             </div>
                         </div>
@@ -35,6 +44,17 @@
                 <th>{{:: 'type' | translate}}</th>
             </tr>
         </thead>
+        <tfoot data-ng-show="policies && (policies.length >= query.max || query.first > 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
         <tbody>
             <tr ng-repeat="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy/{{policy.type}}/{{policy.id}}">{{policy.name}}</a></td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
index 40b2cf9..b1c3978 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-resource-list.html
@@ -10,22 +10,34 @@
                         {{:: 'filter' | translate}}:&nbsp;&nbsp;
                         <div class="form-group">
                             <div class="input-group">
-                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
+                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
                                 <div class="input-group-addon">
-                                    <i class="fa fa-search" type="submit"></i>
+                                    <i class="fa fa-search" id="resourceSearch" type="submit" data-ng-click="firstPage()"></i>
                                 </div>
                             </div>
                             <div class="input-group">
-                                <input type="text" placeholder="{{:: 'authz-owner' | translate}}" data-ng-model="search.owner.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
+                                <input type="text" placeholder="{{:: 'type' | translate}}" data-ng-model="query.type" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
                                 <div class="input-group-addon">
-                                    <i class="fa fa-search" type="submit"></i>
+                                    <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
                                 </div>
                             </div>
                             <div class="input-group">
-                                <select class="form-control search" data-ng-model="search.type"
-                                        ng-options="r.type as r.type for r in resources | unique : 'type'">
-                                    <option value="" selected ng-click="search.type = ''">{{:: 'type' | translate}}</option>
-                                </select>
+                                <input type="text" placeholder="{{:: 'authz-uri' | translate}}" data-ng-model="query.uri" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
+                            </div>
+                            <div class="input-group">
+                                <input type="text" placeholder="{{:: 'authz-owner' | translate}}" data-ng-model="query.owner" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
+                            </div>
+                            <div class="input-group">
+                                <input type="text" placeholder="{{:: 'authz-scope' | translate}}" data-ng-model="query.scope" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
+                                <div class="input-group-addon">
+                                    <i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
+                                </div>
                             </div>
                         </div>
 
@@ -45,6 +57,17 @@
                 <th>{{:: 'actions' | translate}}</th>
             </tr>
         </thead>
+        <tfoot data-ng-show="resources && (resources.length >= query.max || query.first > 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="resources.length < query.max">{{:: 'next-page' | translate}}</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
         <tbody>
             <tr ng-repeat="resource in resources | filter:search | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource/{{resource._id}}">{{resource.name}}</a></td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
index 39cfc77..7886129 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/resource-server-scope-list.html
@@ -9,13 +9,12 @@
                     <div class="form-inline">
                         <div class="form-group">
                             <div class="input-group">
-                                <input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
+                                <input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('scopeSearch').click()">
                                 <div class="input-group-addon">
-                                    <i class="fa fa-search" type="submit"></i>
+                                    <i class="fa fa-search" id="scopeSearch" type="submit" data-ng-click="firstPage()"></i>
                                 </div>
                             </div>
                         </div>
-
                         <div class="pull-right">
                             <a id="createScope" class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/create">{{:: 'create' | translate}}</a>
                         </div>
@@ -29,6 +28,17 @@
                 <th>{{:: 'actions' | translate}}</th>
             </tr>
         </thead>
+        <tfoot data-ng-show="scopes && (scopes.length >= query.max || query.first > 0)">
+        <tr>
+            <td colspan="7">
+                <div class="table-nav">
+                    <button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
+                    <button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
+                    <button data-ng-click="nextPage()" class="next" ng-disabled="scopes.length < query.max">{{:: 'next-page' | translate}}</button>
+                </div>
+            </td>
+        </tr>
+        </tfoot>
         <tbody>
             <tr ng-repeat="scope in scopes | filter:search | orderBy:'name'">
                 <td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/{{scope.id}}">{{scope.name}}</a></td>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html
index 3b6c48c..4a6312b 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-clustering.html
@@ -19,10 +19,10 @@
                                    max="31536000" data-ng-model="client.nodeReRegistrationTimeout"
                                    id="nodeReRegistrationTimeout" name="nodeReRegistrationTimeout"/>
                             <select class="form-control" name="nodeReRegistrationTimeoutUnit" data-ng-model="client.nodeReRegistrationTimeoutUnit" >
-                                <option data-ng-selected="!client.nodeReRegistrationTimeoutUnit">{{:: 'seconds' | translate}}</option>
-                                <option>{{:: 'minutes' | translate}}</option>
-                                <option>{{:: 'hours' | translate}}</option>
-                                <option>{{:: 'days' | translate}}</option>
+                                <option data-ng-selected="!client.nodeReRegistrationTimeoutUnit" value="Seconds">{{:: 'seconds' | translate}}</option>
+                                <option value="Minutes">{{:: 'minutes' | translate}}</option>
+                                <option value="Hours">{{:: 'hours' | translate}}</option>
+                                <option value="Days">{{:: 'days' | translate}}</option>
                             </select>
                         </div>
                     </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
index 1378f78..d8f0d24 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
@@ -333,6 +333,36 @@
             </div>
         </fieldset>
 
+        <fieldset data-ng-show="protocol == 'openid-connect'">
+            <legend collapsed><span class="text">{{:: 'fine-oidc-endpoint-conf' | translate}}</span>  <kc-tooltip>{{:: 'fine-oidc-endpoint-conf.tooltip' | translate}}</kc-tooltip></legend>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'openid-connect'">
+                <label class="col-md-2 control-label" for="userInfoSignedResponseAlg">{{:: 'user-info-signed-response-alg' | translate}}</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="userInfoSignedResponseAlg"
+                                ng-change="changeUserInfoSignedResponseAlg()"
+                                ng-model="userInfoSignedResponseAlg"
+                                ng-options="sig for sig in oidcSignatureAlgorithms">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>{{:: 'user-info-signed-response-alg.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix block" data-ng-show="protocol == 'openid-connect'">
+                <label class="col-md-2 control-label" for="requestObjectSignatureAlg">{{:: 'request-object-signature-alg' | translate}}</label>
+                <div class="col-sm-6">
+                    <div>
+                        <select class="form-control" id="requestObjectSignatureAlg"
+                                ng-change="changeRequestObjectSignatureAlg()"
+                                ng-model="requestObjectSignatureAlg"
+                                ng-options="sig for sig in requestObjectSignatureAlgorithms">
+                        </select>
+                    </div>
+                </div>
+                <kc-tooltip>{{:: 'request-object-signature-alg.tooltip' | translate}}</kc-tooltip>
+            </div>
+        </fieldset>
+
         <div class="form-group">
             <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
                 <button kc-save  data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html b/themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html
index 49d1fae..d2a75c2 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html
@@ -232,7 +232,7 @@
                 <kc-tooltip>{{:: 'debug.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group" data-ng-show="instance.config.allowKerberosAuthentication">
-                <label class="col-md-2 control-label" for="debug">{{:: 'use-kerberos-for-password-authentication' | translate}} </label>
+                <label class="col-md-2 control-label" for="useKerberosForPasswordAuthentication">{{:: 'use-kerberos-for-password-authentication' | translate}} </label>
                 <div class="col-md-6">
                     <input ng-model="instance.config.useKerberosForPasswordAuthentication" id="useKerberosForPasswordAuthentication" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
                 </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html b/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html
index d49561e..bcb3150 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/group-role-mappings.html
@@ -84,7 +84,8 @@
                             </button>
                         </div>
                         <div class="col-md-3">
-                            <label class="control-label" for="client-composite">{{:: 'effective-roles' | translate}} <span tooltip-placement="right" tooltip-trigger="mouseover mouseout" tooltip="{{:: 'group.effective-roles-client.tooltip' | translate}}" class="fa fa-info-circle"></span></label>
+                            <label class="control-label" for="client-composite">{{:: 'effective-roles' | translate}}</label>
+                            <kc-tooltip>{{:: 'group.effective-roles-client.tooltip' | translate}}</kc-tooltip>
                             <select id="client-composite" class="form-control" multiple size=5
                                     disabled="true"
                                     ng-model="dummymodel"
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/menu.html b/themes/src/main/resources/theme/base/admin/resources/partials/menu.html
index 85a9a1c..8523142 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/menu.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/menu.html
@@ -1,13 +1,14 @@
 <div class="navbar-header">
-    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
-        <span class="sr-only">{{:: 'toggle-navigation' | translate}}</span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-    </button>
-    <a class="navbar-brand" href="#/"></a>
+    <button type="button" class="navbar-toggle" ng-init="navCollapsed = true" ng-click="navCollapsed = !navCollapsed">
+      <span class="sr-only">{{:: 'toggle-navigation' | translate}}</span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+  </button>
+  <a class="navbar-brand" href="#"></a>
 </div>
-<div class="collapse navbar-collapse navbar-collapse-1">
+
+<div class="collapse navbar-collapse" collapse="navCollapsed">
     <ul class="nav navbar-nav navbar-utility">
         <li class="dropdown">
             <a href="#" class="dropdown-toggle" data-toggle="dropdown">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html
index 04a6311..b4a66a7 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-admin.html
@@ -46,10 +46,10 @@
                         </div>
                         <div class="form-group">
                             <label class="col-sm-2 control-label" for="resource">{{:: 'resource-path' | translate}}</label>
+                            <kc-tooltip>{{:: 'resource-path.tooltip' | translate}}</kc-tooltip>
                             <div class="col-sm-4">
                                 <input class="form-control" type="text" id="resource" name="resource" data-ng-model="query.resourcePath">
                             </div>
-                            <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'resource-path.tooltip' | translate}}" class="fa fa-info-circle"></span>
                         </div>
                         <div class="form-group">
                             <label class="col-sm-2 control-label" for="dateFrom">{{:: 'date-(from)' | translate}}</label>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
index 8f36f6a..a304784 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-events-config.html
@@ -17,14 +17,12 @@
             <fieldset class="border-top">
                 <div class="form-group">
                     <label class="col-md-2 control-label" for="eventsListeners" class="control-label">{{:: 'event-listeners' | translate}}</label>
-
+                    <kc-tooltip>{{:: 'event-listeners.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <select ui-select2 ng-model="eventsConfig.eventsListeners" data-placeholder="{{:: 'select-an-action.placeholder' | translate}}" multiple>
                             <option ng-repeat="listener in eventListeners" value="{{listener}}">{{listener}}</option>
                         </select>
                     </div>
-
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'event-listeners.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
             </fieldset>
 
@@ -33,41 +31,37 @@
 
                 <div class="form-group">
                     <label class="col-md-2 control-label" for="enabled">{{:: 'save-events' | translate}}</label>
+                    <kc-tooltip>{{:: 'login.save-events.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <input ng-model="eventsConfig.eventsEnabled" name="enabled" id="enabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
                     </div>
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'login.save-events.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
 
                 <div class="form-group" data-ng-show="eventsConfig.eventsEnabled">
                     <label class="col-md-2 control-label" for="enabledEventTypes" class="control-label">{{:: 'saved-types' | translate}}</label>
-
+                    <kc-tooltip>{{:: 'saved-types.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <input ui-select2="eventSelectOptions" id="enabledEventTypes" ng-model="eventsConfig.enabledEventTypes" data-placeholder="{{:: 'select-event-types.placeholder' | translate}}"/>
                     </div>
-
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'saved-types.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
 
                 <div class="form-group" data-ng-show="access.manageEvents && eventsConfig.eventsEnabled">
                     <label class="col-md-2 control-label" for="password">{{:: 'clear-events' | translate}}</label>
+                    <kc-tooltip>{{:: 'clear-events.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <button class="btn btn-danger" type="submit" data-ng-click="clearEvents()" >{{:: 'clear-events' | translate}}</button>
                     </div>
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'clear-events.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
-                <div class="form-group input-select" data-ng-show="eventsConfig.eventsEnabled">
+                <div class="form-group" data-ng-show="eventsConfig.eventsEnabled">
                     <label class="col-md-2 control-label" for="expiration">{{:: 'expiration' | translate}}</label>
-                    <div class="col-md-6">
+                    <kc-tooltip>{{:: 'events.expiration.tooltip' | translate}}</kc-tooltip>
+                    <div class="col-md-6 time-selector">
                         <input class="form-control" type="number" data-ng-model="eventsConfig.eventsExpiration" id="expiration" name="expiration" min="0"/>
-                    </div>
-                    <div class="col-md-2 select-kc">
-                        <select name="expirationUnit" data-ng-model="eventsConfig.expirationUnit" >
-                            <option>{{:: 'minutes' | translate}}</option>
-                            <option>{{:: 'hours' | translate}}</option>
-                            <option>{{:: 'days' | translate}}</option>
+                        <select class="form-control" name="expirationUnit" data-ng-model="eventsConfig.expirationUnit">
+                            <option value="Minutes">{{:: 'minutes' | translate}}</option>
+                            <option value="Hours">{{:: 'hours' | translate}}</option>
+                            <option value="Days">{{:: 'days' | translate}}</option>
                         </select>
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'events.expiration.tooltip' | translate}}" class="fa fa-info-circle"></span>
                     </div>
                 </div>
             </fieldset>
@@ -78,28 +72,26 @@
 
                 <div class="form-group">
                     <label class="col-md-2 control-label" for="adminEventsEnabled">{{:: 'save-events' | translate}}</label>
+                    <kc-tooltip>{{:: 'admin.save-events.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <input ng-model="eventsConfig.adminEventsEnabled" name="adminEventsEnabled" id="adminEventsEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
                     </div>
-
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'admin.save-events.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
 
                 <div class="form-group" data-ng-show="eventsConfig.adminEventsEnabled">
                     <label class="col-md-2 control-label" for="adminEventsDetailsEnabled">{{:: 'include-representation' | translate}}</label>
+                    <kc-tooltip>{{:: 'include-representation.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <input ng-model="eventsConfig.adminEventsDetailsEnabled" name="adminEventsDetailsEnabled" id="adminEventsDetailsEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
                     </div>
-
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'include-representation.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
                 
                 <div class="form-group" data-ng-show="access.manageEvents && eventsConfig.adminEventsEnabled">
                     <label class="col-md-2 control-label" for="password">{{:: 'clear-admin-events' | translate}}</label>
+                    <kc-tooltip>{{:: 'clear-admin-events.tooltip' | translate}}</kc-tooltip>
                     <div class="col-md-6">
                         <button class="btn btn-danger" type="submit" data-ng-click="clearAdminEvents()" >{{:: 'clear-admin-events' | translate}}</button>
                     </div>
-                    <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'clear-admin-events.tooltip' | translate}}" class="fa fa-info-circle"></span>
                 </div>
                 
             </fieldset>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
index 1db4c6a..81690be 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-oidc.html
@@ -118,13 +118,13 @@
                 </div>
                 <kc-tooltip>{{:: 'identity-provider.logout-url.tooltip' | translate}}</kc-tooltip>
             </div>
-                    <div class="form-group">
-                        <label class="col-sm-2 control-label" for="backchannelSupported">{{:: 'backchannel-logout' | translate}}</label>
-                        <div class="col-sm-4">
-                            <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
-                        </div>
-                        <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'backchannel-logout.tooltip' | translate}}" class="fa fa-info-circle"></span>
-                    </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label" for="backchannelSupported">{{:: 'backchannel-logout' | translate}}</label>
+                <div class="col-sm-4">
+                    <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
+                </div>
+                <kc-tooltip>{{:: 'backchannel-logout.tooltip' | translate}}</kc-tooltip>
+            </div>
             <div class="form-group clearfix">
                 <label class="col-md-2 control-label" for="userInfoUrl">{{:: 'user-info-url' | translate}}</label>
                 <div class="col-md-6">
@@ -167,9 +167,9 @@
                         <select class="form-control" id="prompt" ng-model="identityProvider.config.prompt">
                             <option value="">{{:: 'unspecified.option' | translate}}</option>
                             <option value="none">{{:: 'none.option' | translate}}</option>
-                            <option>{{:: 'consent.option' | translate}}</option>
-                            <option>{{:: 'login.option' | translate}}</option>
-                            <option>{{:: 'select-account.option' | translate}}</option>
+                            <option value="consent">{{:: 'consent.option' | translate}}</option>
+                            <option value="login">{{:: 'login.option' | translate}}</option>
+                            <option value="select_account">{{:: 'select-account.option' | translate}}</option>
                         </select>
                     </div>
                 </div>
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index aa94559..f9b8c74 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -109,13 +109,13 @@
                 </div>
                 <kc-tooltip>{{:: 'saml.single-logout-service-url.tooltip' | translate}}</kc-tooltip>
             </div>
-                    <div class="form-group">
-                        <label class="col-sm-2 control-label" for="backchannelSupported">{{:: 'backchannel-logout' | translate}}</label>
-                        <div class="col-sm-4">
-                            <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
-                        </div>
-                        <span tooltip-trigger="mouseover mouseout" tooltip-placement="right" tooltip="{{:: 'backchannel-logout.tooltip' | translate}}" class="fa fa-info-circle"></span>
-                    </div>
+            <div class="form-group">
+                <label class="col-sm-2 control-label" for="backchannelSupported">{{:: 'backchannel-logout' | translate}}</label>
+                <div class="col-sm-4">
+                    <input ng-model="identityProvider.config.backchannelSupported" id="backchannelSupported" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
+                </div>
+                <kc-tooltip>{{:: 'backchannel-logout.tooltip' | translate}}</kc-tooltip>
+            </div>
             <div class="form-group clearfix">
                 <label class="col-md-2 control-label" for="nameIDPolicyFormat">{{:: 'nameid-policy-format' | translate}}</label>
                 <div class="col-md-6">
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html b/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
index fd1a0fa..9970be4 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/role-mappings.html
@@ -84,7 +84,8 @@
                             </button>
                         </div>
                         <div class="col-md-3">
-                            <label class="control-label" for="client-composite">{{:: 'effective-roles' | translate}} <span tooltip-placement="right" tooltip-trigger="mouseover mouseout" tooltip="{{:: 'user.effective-roles-client.tooltip' | translate}}" class="fa fa-info-circle"></span></label>
+                            <label class="control-label" for="client-composite">{{:: 'effective-roles' | translate}}</label>
+                            <kc-tooltip>{{:: 'user.effective-roles-client.tooltip' | translate}}</kc-tooltip>
                             <select id="client-composite" class="form-control" multiple size=5
                                     disabled="true"
                                     ng-model="dummymodel"
diff --git a/themes/src/main/resources/theme/base/admin/theme.properties b/themes/src/main/resources/theme/base/admin/theme.properties
index 67fb523..0533ca8 100644
--- a/themes/src/main/resources/theme/base/admin/theme.properties
+++ b/themes/src/main/resources/theme/base/admin/theme.properties
@@ -1,2 +1,2 @@
 import=common/keycloak
-locales=ca,de,en,es,fr,it,pt-BR,ru
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/email/messages/messages_ja.properties b/themes/src/main/resources/theme/base/email/messages/messages_ja.properties
new file mode 100644
index 0000000..087170a
--- /dev/null
+++ b/themes/src/main/resources/theme/base/email/messages/messages_ja.properties
@@ -0,0 +1,25 @@
+# encoding: utf-8
+emailVerificationSubject=Eメールの確認
+emailVerificationBody=このメールアドレスで {2} アカウントが作成されたました。以下のリンクをクリックしてメールアドレスの確認を完了してください。\n\n{0}\n\nこのリンクは {1} 分間だけ有効です。\n\nもしこのアカウントの作成に心当たりがない場合は、このメールを無視してください。
+emailVerificationBodyHtml=<p>このメールアドレスで {2} アカウントが作成されました。以下のリンクをクリックしてメールアドレスの確認を完了してください。</p><p><a href="{0}">{0}</a></p><p>このリンクは {1} 分間だけ有効です。</p><p>もしこのアカウントの作成に心当たりがない場合は、このメールを無視してください。</p>
+identityProviderLinkSubject=リンク {0}
+identityProviderLinkBody=あなたの "{1}" アカウントと {2} ユーザーの "{0}" アカウントのリンクが要求されました。以下のリンクをクリックしてアカウントのリンクを行ってください。\n\n{3}\n\nこのリンクは {4} 分間だけ有効です。\n\nもしアカウントのリンクを行わない場合は、このメッセージを無視してください。アカウントのリンクを行うことで、{0} 経由で {1} にログインすることができるようになります。
+identityProviderLinkBodyHtml=<p>あなたの <b>{1}</b> アカウントと {2} ユーザーの <b>{0}</b> アカウントのリンクが要求されました。以下のリンクをクリックしてアカウントのリンクを行ってください。</p><p><a href="{3}">{3}</a></p><p>このリンクは {4} 分間だけ有効です。</p><p>もしアカウントのリンクを行わない場合は、このメッセージを無視してください。アカウントのリンクを行うことで、{0} 経由で {1} にログインすることができるようになります。</p>
+passwordResetSubject=パスワードのリセット
+passwordResetBody=あなたの {2} アカウントのクレデンシャルの変更が要求されています。以下のリンクをクリックしてクレデンシャルのリセットを行ってください。\n\n{0}\n\nこのリンクとコードは {1} 分間だけ有効です。\n\nもしクレデンシャルのリセットを行わない場合は、このメッセージを無視してください。何も変更されません。
+passwordResetBodyHtml=<p>あなたの {2} アカウントのクレデンシャルの変更が要求されています。以下のリンクをクリックしてクレデンシャルのリセットを行ってください。</p><p><a href="{0}">{0}</a></p><p>このリンクとコードは {1} 分間だけ有効です。</p><p>もしクレデンシャルのリセットを行わない場合は、このメッセージを無視してください。何も変更されません。</p>
+executeActionsSubject=アカウントの更新
+executeActionsBody=管理者よりあなたの {2} アカウントの更新が要求されています。以下のリンクをクリックしてこのプロセスを開始してください。\n\n{0}\n\nこのリンクは {1} 分間だけ有効です。\n\n管理者からのこの変更要求についてご存知ない場合は、このメッセージを無視してください。何も変更されません。
+executeActionsBodyHtml=<p>管理者よりあなたの {2} アカウントの更新が要求されています。以下のリンクをクリックしてこのプロセスを開始してください。</p><p><a href="{0}">{0}</a></p><p>このリンクは {1} 分間だけ有効です。</p><p>管理者からのこの変更要求についてご存知ない場合は、このメッセージを無視してください。何も変更されません。</p>
+eventLoginErrorSubject=ログインエラー
+eventLoginErrorBody={0} に {1} からのログイン失敗があなたのアカウントで検出されました。心当たりがない場合は、管理者に連絡してください。
+eventLoginErrorBodyHtml=<p>{0} に {1} からのログイン失敗があなたのアカウントで検出されました。心当たりがない場合は管理者に連絡してください。</p>
+eventRemoveTotpSubject=TOTPの削除
+eventRemoveTotpBody={0} に {1} からの操作で TOTP が削除されました。心当たりがない場合は、管理者に連絡してください。
+eventRemoveTotpBodyHtml=<p>{0} に {1} からの操作で TOTP が削除されました。心当たりがない場合は、管理者に連絡してください。</p>
+eventUpdatePasswordSubject=パスワードの更新
+eventUpdatePasswordBody={0} に {1} からの操作であなたのパスワードが変更されました。心当たりがない場合は、管理者に連絡してください。
+eventUpdatePasswordBodyHtml=<p>{0} に {1} からの操作であなたのパスワードが変更されました。心当たりがない場合は、管理者に連絡してください。</p>
+eventUpdateTotpSubject=TOTPの更新
+eventUpdateTotpBody={0} に {1} からの操作で TOTP が更新されました。心当たりがない場合は、管理者に連絡してください。
+eventUpdateTotpBodyHtml=<p>{0} に {1} からの操作で TOTP が更新されました。心当たりがない場合は、管理者に連絡してください。</p>
diff --git a/themes/src/main/resources/theme/base/email/messages/messages_no.properties b/themes/src/main/resources/theme/base/email/messages/messages_no.properties
new file mode 100644
index 0000000..32334e9
--- /dev/null
+++ b/themes/src/main/resources/theme/base/email/messages/messages_no.properties
@@ -0,0 +1,24 @@
+emailVerificationSubject=Bekreft e-postadresse
+emailVerificationBody=Noen har opprettet en {2} konto med denne e-postadressen. Hvis dette var deg, klikk p\u00E5 lenken nedenfor for \u00E5 bekrefte e-postadressen din\n\n{0}\n\nDenne lenken vil utl\u00F8pe om {1} minutter.\n\nHvis du ikke opprettet denne kontoen, vennligst ignorer denne meldingen.
+emailVerificationBodyHtml=<p>Noen har opprettet en {2} konto med denne e-postadressen. Hvis dette var deg, klikk p\u00E5 lenken nedenfor for \u00E5 bekrefte e-postadressen din</p><p><a href="{0}">{0}</a></p><p>Denne lenken vil utl\u00F8pe om {1} minutter.</p><p>Hvis du ikke opprettet denne kontoen, vennligst ignorer denne meldingen.</p>
+identityProviderLinkSubject=Lenke {0}
+identityProviderLinkBody=Noen vil koble din <b>{1}</b> konto med <b>{0}</b> konto til bruker {2}. Hvis dette var deg, klikk p\u00E5 lenken nedenfor for \u00E5 koble kontoene\n\n{3}\n\nDenne lenken vil utl\u00F8pe om {4} minutter\n\nHvis du ikke vil koble kontoene, vennligst ignorer denne meldingen. Hvis du kobler kontoene sammen vil du kunne logge inn til {1} gjennom {0}.
+identityProviderLinkBodyHtml=<p>Noen vil koble din <b>{1}</b> konto med <b>{0}</b> konto til bruker {2}. Hvis dette var deg, klikk p\u00E5 lenken nedenfor for \u00E5 koble kontoene.</p><p><a href="{3}">{3}</a></p><p>Denne lenken vil utl\u00F8pe om {4} minutter.</p><p>Hvis du ikke vil koble kontoene, vennligst ignorer denne meldingen. Hvis du kobler kontoene sammen vil du kunne logge inn til {1} gjennom {0}.</p>
+passwordResetSubject=Tilbakestill passord
+passwordResetBody=Noen har bedt om \u00E5 endre innloggingsdetaljene til din konto {2}. Hvis dette var deg, klikk p\u00E5 lenken nedenfor for \u00E5 tilbakestille dem.\n\n{0}\n\nDenne lenken vil utl\u00F8pe om {1} minutter.\n\nHvis du ikke vil tilbakestille din innloggingsdata, vennligst ignorer denne meldingen og ingenting vil bli endret.
+passwordResetBodyHtml=<p>Noen har bedt om \u00E5 endre innloggingsdetaljene til din konto {2}. Hvis dette var deg, klikk p\u00E5 lenken nedenfor for \u00E5 tilbakestille dem.</p><p><a href="{0}">{0}</a></p><p>Denne lenken vil utl\u00F8pe om {1} minutter.</p><p>Hvis du ikke vil tilbakestille din innloggingsdata, vennligst ignorer denne meldingen og ingenting vil bli endret.</p>
+executeActionsSubject=Oppdater kontoen din
+executeActionsBody=Administrator har anmodet at du oppdaterer din {2} konto. Klikk p\u00E5 lenken nedenfor for \u00E5 starte denne prosessen\n\n{0}\n\nDenne lenken vil utl\u00F8pe om {1} minutter.\n\nHvis du ikke var klar over at administrator har bedt om dette, vennligst ignorer denne meldingen og ingenting vil bli endret.
+executeActionsBodyHtml=<p>Administrator har anmodet at du oppdaterer din {2} konto. Klikk p\u00E5 linken nedenfor for \u00E5 starte denne prosessen.</p><p><a href="{0}">{0}</a></p><p>Denne lenken vil utl\u00F8pe om {1} minutter.</p><p>Hvis du ikke var klar over at administrator har bedt om dette, ignorer denne meldingen og ingenting vil bli endret. </p>
+eventLoginErrorSubject=Innlogging feilet
+eventLoginErrorBody=Et mislykket innloggingsfors\u00F8k ble oppdaget p\u00E5 din konto p\u00E5 {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator.
+eventLoginErrorBodyHtml=<p>Et mislykket innloggingsfors\u00F8k ble oppdaget p\u00E5 din konto p\u00E5 {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator.</p>
+eventRemoveTotpSubject=Fjern engangskode
+eventRemoveTotpBody=Engangskode ble fjernet fra kontoen din p\u00E5 {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator.
+eventRemoveTotpBodyHtml=<p>Engangskode ble fjernet fra kontoen din p\u00E5 {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator.</p>
+eventUpdatePasswordSubject=Oppdater passord
+eventUpdatePasswordBody=Ditt passord ble endret i {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator.
+eventUpdatePasswordBodyHtml=<p>Ditt passord ble endret i {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator. </p>
+eventUpdateTotpSubject=Oppdater engangskode
+eventUpdateTotpBody=Engangskode ble oppdatert for kontoen din p\u00E5 {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator.
+eventUpdateTotpBodyHtml=<p>Engangskode ble oppdatert for kontoen din p\u00E5 {0} fra {1}. Hvis dette ikke var deg, vennligst kontakt administrator. </p>
diff --git a/themes/src/main/resources/theme/base/email/theme.properties b/themes/src/main/resources/theme/base/email/theme.properties
index 503eda7..deb2dc9 100644
--- a/themes/src/main/resources/theme/base/email/theme.properties
+++ b/themes/src/main/resources/theme/base/email/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,pt-BR,ru
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
diff --git a/themes/src/main/resources/theme/base/login/login-reset-password.ftl b/themes/src/main/resources/theme/base/login/login-reset-password.ftl
index 404de17..a561b2a 100755
--- a/themes/src/main/resources/theme/base/login/login-reset-password.ftl
+++ b/themes/src/main/resources/theme/base/login/login-reset-password.ftl
@@ -8,7 +8,7 @@
         <form id="kc-reset-password-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
             <div class="${properties.kcFormGroupClass!}">
                 <div class="${properties.kcLabelWrapperClass!}">
-                    <label for="username" class="${properties.kcLabelClass!}">${msg("usernameOrEmail")}</label>
+                    <label for="username" class="${properties.kcLabelClass!}"><#if !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
                 </div>
                 <div class="${properties.kcInputWrapperClass!}">
                     <input type="text" id="username" name="username" class="${properties.kcInputClass!}" autofocus/>
@@ -30,4 +30,4 @@
     <#elseif section = "info" >
         ${msg("emailInstruction")}
     </#if>
-</@layout.registrationLayout>
\ No newline at end of file
+</@layout.registrationLayout>
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_en.properties b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
index 725705e..b07446b 100755
--- a/themes/src/main/resources/theme/base/login/messages/messages_en.properties
+++ b/themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -214,6 +214,8 @@ locale_en=English
 locale_es=Espa\u00F1ol
 locale_fr=Fran\u00e7ais
 locale_it=Italian
+locale_ja=\u65E5\u672C\u8A9E
+locale_no=Norsk
 locale_pt_BR=Portugu\u00EAs (Brasil)
 locale_pt-BR=Portugu\u00EAs (Brasil)
 locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
@@ -225,4 +227,4 @@ clientDisabledMessage=Client disabled.
 invalidParameterMessage=Invalid parameter\: {0}
 alreadyLoggedIn=You are already logged in.
 
-p3pPolicy=CP="This is not a P3P policy!"
\ No newline at end of file
+p3pPolicy=CP="This is not a P3P policy!"
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_ja.properties b/themes/src/main/resources/theme/base/login/messages/messages_ja.properties
new file mode 100644
index 0000000..e0d1fd8
--- /dev/null
+++ b/themes/src/main/resources/theme/base/login/messages/messages_ja.properties
@@ -0,0 +1,218 @@
+# encoding: utf-8
+doLogIn=ログイン
+doRegister=登録
+doCancel=キャンセル
+doSubmit=送信
+doYes=はい
+doNo=いいえ
+doContinue=続ける
+doAccept=承諾
+doDecline=却下
+doForgotPassword=パスワードをお忘れですか?
+doClickHere=クリックしてください
+doImpersonate=代理ログイン
+kerberosNotConfigured=Kerberos は設定されていません
+kerberosNotConfiguredTitle=Kerberos は設定されていません
+bypassKerberosDetail=Kerberos 経由でログインしていないか、ブラウザーで Kerberos ログインの設定がされていません。他の手段でログインするには 「続ける」 をクリックしてください。
+kerberosNotSetUp=Kerberos が設定されていません。ログインできません。
+registerWithTitle={0} で登録
+registerWithTitleHtml={0}
+loginTitle={0} にログイン
+loginTitleHtml={0}
+impersonateTitle={0} ユーザーの代理
+impersonateTitleHtml=<strong>{0}</strong> ユーザーの代理</strong>
+realmChoice=レルム
+unknownUser=不明なユーザー
+loginTotpTitle=モバイル Authenticator セットアップ
+loginProfileTitle=アカウント情報の更新
+loginTimeout=ログインに時間がかかりすぎています。最初からログイン処理を開始します。
+oauthGrantTitle=Grant アクセス
+oauthGrantTitleHtml={0}
+errorTitle=申し訳ございません
+errorTitleHtml=<strong>申し訳ございません</strong>
+emailVerifyTitle=Eメール確認
+emailForgotTitle=パスワードをお忘れですか?
+updatePasswordTitle=パスワード更新
+codeSuccessTitle=成功コード
+codeErrorTitle=エラーコード\: {0}
+
+termsTitle=利用規約
+termsTitleHtml=利用規約
+termsText=<p>利用規約はここで設定する必要があります</p>
+
+recaptchaFailed=無効な reCAPTCHA
+recaptchaNotConfigured=reCAPTCHA が必須ですが、設定されていません
+consentDenied=同意は拒否されました。
+
+noAccount=新規ユーザーですか?
+username=ユーザー名
+usernameOrEmail=ユーザー名 または メールアドレス
+firstName=名
+givenName=名
+fullName=氏名
+lastName=姓
+familyName=姓
+email=Eメール
+password=パスワード
+passwordConfirm=パスワード (確認)
+passwordNew=新しいパスワード
+passwordNewConfirm=新しいパスワード (確認)
+rememberMe=ログイン状態の保存
+authenticatorCode=ワンタイムコード
+address=住所
+street=番地
+locality=市区町村
+region=都道府県
+postal_code=郵便番号
+country=国
+emailVerified=確認済みEメール
+gssDelegationCredential=GSS 代行クレデンシャル
+
+loginTotpStep1=<a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> または Google Authenticator (Google認証システム) をご自身のデバイスにインストールしてください。これらのアプリケーションは <a href="https://play.google.com">Google Play</a> と Apple App Store で入手できます。
+loginTotpStep2=アプリケーションを開きバーコードをスキャンするかキーを入力してください。
+loginTotpStep3=アプリケーションで提供されたワンタイムコードを入力して送信をクリックし、セットアップを完了してください。
+loginTotpOneTime=ワンタイムコード
+
+oauthGrantRequest=アクセス権を許可してよろしいでしょうか?
+inResource=in
+
+emailVerifyInstruction1=メールアドレスを確認する手順を記載したEメールを送信しました。
+emailVerifyInstruction2=Eメールで確認コードを受け取っていませんか?
+emailVerifyInstruction3=Eメールを再送信します。
+
+emailLinkIdpTitle=リンク {0}
+emailLinkIdp1={0} の {1} アカウントを あなたの {2} アカウントとリンクするための手順を記載したEメールを送信しました。
+emailLinkIdp2=Eメールで確認コードを受け取っていませんか?
+emailLinkIdp3=Eメールを再送信します。
+
+backToLogin=&laquo; ログインに戻る
+
+emailInstruction=ユーザー名またメールアドレスを入力してください。新しいパスワードの設定方法をご案内いたします。
+
+copyCodeInstruction=このコードをコピーし、あなたのアプリケーションにペーストしてください:
+
+personalInfo=個人情報:
+role_admin=管理者
+role_realm-admin=レルム管理者
+role_create-realm=レルムの作成
+role_create-client=クライアントの作成
+role_view-realm=レルムの参照
+role_view-users=ユーザーの参照
+role_view-applications=アプリケーションの参照
+role_view-clients=クライアントの参照
+role_view-events=イベントの参照
+role_view-identity-providers=アイデンティティ プロバイダーの参照
+role_manage-realm=レルムの管理
+role_manage-users=ユーザーの管理
+role_manage-applications=アプリケーションの管理
+role_manage-identity-providers=アイデンティティ プロバイダーの管理
+role_manage-clients=クライアントの管理
+role_manage-events=イベントの管理
+role_view-profile=プロフィールの参照
+role_manage-account=アカウントの管理
+role_read-token=トークンの読み取り
+role_offline-access=オフラインアクセス
+client_account=アカウント
+client_security-admin-console=セキュリティ管理コンソール
+client_admin-cli=管理 CLI
+client_realm-management=レルム管理
+client_broker=ブローカー
+
+invalidUserMessage=無効なユーザー名またはパスワードです。
+invalidEmailMessage=無効なメールアドレスです。
+accountDisabledMessage=アカウントは無効です。管理者に連絡してください。
+accountTemporarilyDisabledMessage=アカウントは一時的に無効です。管理者に連絡、またはしばらく時間をおいてから再度お試しください。
+expiredCodeMessage=ログインタイムアウトが発生しました。再度ログインしてください。
+
+missingFirstNameMessage=名を指定してください。
+missingLastNameMessage=姓を指定してください。
+missingEmailMessage=Eメールを指定してください。
+missingUsernameMessage=ユーザー名を指定してください。
+missingPasswordMessage=パスワードを指定してください。
+missingTotpMessage=Authenticator コードを指定してください。
+notMatchPasswordMessage=パスワードが一致していません。
+
+invalidPasswordExistingMessage=間違った既存のパスワードです。
+invalidPasswordConfirmMessage=パスワード確認が一致していません。
+invalidTotpMessage=間違った Authenticator コードです。
+
+usernameExistsMessage=既に存在するユーザー名です。
+emailExistsMessage=既に存在するEメールです。
+
+federatedIdentityExistsMessage={0} {1} のユーザーは既に存在します。そのアカウントををリンクするにはアカウント管理にログインしてください。
+
+confirmLinkIdpTitle=既に存在するアカウントです。
+federatedIdentityConfirmLinkMessage={0} {1} のユーザーは既に存在します。継続しますか?
+federatedIdentityConfirmReauthenticateMessage={1} でアカウントをリンクするために {0} として認証します
+confirmLinkIdpReviewProfile=プロフィールの確認
+confirmLinkIdpContinue=既存のアカウントに追加する
+
+configureTotpMessage=アカウントを有効にするにはモバイル Authenticator のセットアップが必要です。
+updateProfileMessage=アカウントを有効にするにはユーザープロフィールの更新が必要です。
+updatePasswordMessage=アカウントを有効にするにはパスワードの更新が必要です。
+verifyEmailMessage=アカウントを有効にするにはメールアドレスの確認が必要です。
+linkIdpMessage=アカウントを {0} とリンクするにはメールアドレスの確認が必要です。
+
+emailSentMessage=詳細な手順を記載したEメールをすぐに受信してください。
+emailSendErrorMessage=Eメールの送信に失敗しました。しばらく時間をおいてから再度お試しください。
+
+accountUpdatedMessage=アカウントが更新されました。
+accountPasswordUpdatedMessage=パスワードが更新されました。
+
+noAccessMessage=アクセスがありません
+
+invalidPasswordMinLengthMessage=無効なパスワード: 最小 {0} の長さが必要です。
+invalidPasswordMinDigitsMessage=無効なパスワード: 少なくとも {0} 文字の数字を含む必要があります。
+invalidPasswordMinLowerCaseCharsMessage=無効なパスワード: 少なくとも {0} 文字の小文字を含む必要があります。
+invalidPasswordMinUpperCaseCharsMessage=無効なパスワード: 少なくとも {0} 文字の大文字を含む必要があります。
+invalidPasswordMinSpecialCharsMessage=無効なパスワード:  少なくとも {0} 文字の特殊文字を含む必要があります。
+invalidPasswordNotUsernameMessage=無効なパスワード: ユーザー名と同じパスワードは禁止されています。
+invalidPasswordRegexPatternMessage=無効なパスワード: 正規表現パターンと一致しません。
+invalidPasswordHistoryMessage=無効なパスワード: 最近の {0} パスワードのいずれかと同じパスワードは禁止されています。
+
+failedToProcessResponseMessage=応答を処理できませんでした
+httpsRequiredMessage=HTTPS が必須です
+realmNotEnabledMessage=レルムが有効ではありません
+invalidRequestMessage=無効なリクエストです
+failedLogout=ログアウトに失敗しました
+unknownLoginRequesterMessage=不明なログイン要求元です
+loginRequesterNotEnabledMessage=ログイン要求元は有効ではありません
+bearerOnlyMessage=bearer-only のアプリケーションはブラウザーログインを開始することが許可されていません
+standardFlowDisabledMessage=与えられた response_type でクライアントはブラウザーログインを開始することが許可されていません。 Standard Flow は無効です。
+implicitFlowDisabledMessage=与えられた response_type でクライアントはブラウザーログインを開始することが許可されていません。 Implicit Flow は無効です。
+invalidRedirectUriMessage=無効なリダイレクト URI です
+unsupportedNameIdFormatMessage=サポートされていない NameID Format です
+invalidRequesterMessage=無効な要求元です
+registrationNotAllowedMessage=登録は許可されていません
+resetCredentialNotAllowedMessage=クレデンシャルのリセットは許可されていません
+
+permissionNotApprovedMessage=アクセス権は承認されていません。
+noRelayStateInResponseMessage=アイデンティティ プロバイダーからの応答に RelayState がありません。
+insufficientPermissionMessage=アイデンティティにリンクするには不十分なアクセス権です。
+couldNotProceedWithAuthenticationRequestMessage=アイデンティティ プロバイダーに認証要求を続行できませんでした。
+couldNotObtainTokenMessage=アイデンティティ プロバイダーからトークンを取得できませんでした。
+unexpectedErrorRetrievingTokenMessage=アイデンティティ プロバイダーからのトークン取得で予期せぬエラーが発生しました。
+unexpectedErrorHandlingResponseMessage=アイデンティティ プロバイダーからの応答を処理する際に予期せぬエラーが発生しました。
+identityProviderAuthenticationFailedMessage=認証に失敗しました。アイデンティティ プロバイダーを使用して認証できませんでした。
+identityProviderDifferentUserMessage={1} として認証されることを期待していましたが、{0} として認証されました
+couldNotSendAuthenticationRequestMessage=アイデンティティ プロバイダーに認証要求を送信することができませんでした。
+unexpectedErrorHandlingRequestMessage=アイデンティティ プロバイダーへの認証要求を処理する際に予期せぬエラーが発生しました。
+invalidAccessCodeMessage=無効なアクセスコードです。
+sessionNotActiveMessage=セッションが有効ではありません。
+invalidCodeMessage=エラーが発生しました。アプリケーションを介して再度ログインしてください。
+identityProviderUnexpectedErrorMessage=アイデンティティ プロバイダーによる認証の再に予期せぬエラーが発生しました
+identityProviderNotFoundMessage=該当の識別子を持つアイデンティティ プロバイダーが見つかりませんでした。
+identityProviderLinkSuccess=アカウントが正常に {0} の {1} アカウントにリンクされました。
+staleCodeMessage=このページはもはや有効ではありませんので、アプリケーションに戻り再度ログインしてください
+realmSupportsNoCredentialsMessage=レルムはクレデンシャルタイプをサポートしていません。
+identityProviderNotUniqueMessage=レルムは複数のアイデンティティ プロバイダーをサポートしています。どのアイデンティティ プロバイダーが認証に使用されるべきか判断できませんでした。
+emailVerifiedMessage=メールアドレスが確認できました。
+staleEmailVerificationLink=クリックされたリンクは古いリンクでありもはや有効ではありません。おそらくEメールは既に確認済みではないでしょうか?
+
+backToApplication=&laquo; アプリケーションに戻る
+missingParameterMessage=不足パラメータ\: {0}
+clientNotFoundMessage=クライアントが見つかりません。
+clientDisabledMessage=クライアントが無効になっています。
+invalidParameterMessage=無効なパラメータ\: {0}
+alreadyLoggedIn=既にログインしています。
+
diff --git a/themes/src/main/resources/theme/base/login/messages/messages_no.properties b/themes/src/main/resources/theme/base/login/messages/messages_no.properties
new file mode 100644
index 0000000..a90af46
--- /dev/null
+++ b/themes/src/main/resources/theme/base/login/messages/messages_no.properties
@@ -0,0 +1,229 @@
+doLogIn=Logg inn
+doRegister=Registrer deg
+doCancel=Avbryt
+doSubmit=Send inn
+doYes=Ja
+doNo=Nei
+doContinue=Fortsett
+doAccept=Aksepter
+doDecline=Avsl\u00E5
+doForgotPassword=Glemt passord?
+doClickHere=Klikk her
+doImpersonate=Utgi deg for \u00E5 v\u00E6re en annen bruker
+kerberosNotConfigured=Kerberos er ikke konfigurert
+kerberosNotConfiguredTitle=Kerberos er ikke konfigurert
+bypassKerberosDetail=Enten er du ikke logget inn via Kerberos eller s\u00E5 st\u00F8tter ikke nettleseren innlogging med Kerberos. Vennligst klikk Fortsett for \u00E5 logge inn p\u00E5 andre m\u00E5ter
+kerberosNotSetUp=Kerberos er ikke konfigurert. Du kan ikke logge inn.
+registerWithTitle=Registrer deg med {0}
+registerWithTitleHtml={0}
+loginTitle=Logg inn p\u00E5 {0}
+loginTitleHtml={0}
+impersonateTitle={0} Gi deg ut for \u00E5 v\u00E6re en annen bruker
+impersonateTitleHtml=<strong>{0} Gi deg ut for \u00E5 v\u00E6re en annen bruker</strong>
+realmChoice=Sikkerhetsdomene
+unknownUser=Ukjent bruker
+loginTotpTitle=Konfigurer autentifikator for mobil
+loginProfileTitle=Oppdater konto
+loginTimeout=Du brukte for lang tid p\u00E5 \u00E5 logge inn. Vennligst pr\u00F8v igjen.
+oauthGrantTitle=Gi tilgang
+oauthGrantTitleHtml={0}
+errorTitle=Vi beklager...
+errorTitleHtml=Vi <strong>beklager</strong> ...
+emailVerifyTitle=E-postbekreftelse
+emailForgotTitle=Glemt passord?
+updatePasswordTitle=Oppdater passord
+codeSuccessTitle=Suksesskode
+codeErrorTitle=Feilkode\: {0}
+
+termsTitle=Vilk\u00E5r og betingelser
+termsTitleHtml=Vilk\u00E5r og betingelser
+termsText=<p>Vilk\u00E5r og betingelser kommer</p>
+
+recaptchaFailed=Ugyldig Bildebekreftelse
+recaptchaNotConfigured=Bildebekreftelse er p\u00E5krevet, men er ikke konfigurert
+consentDenied=Samtykke avsl\u00E5tt.
+
+noAccount=Ny bruker?
+username=Brukernavn
+usernameOrEmail=Brukernavn eller e-postadresse
+firstName=Fornavn
+givenName=Fornavn
+fullName=Fullstendig navn
+lastName=Etternavn
+familyName=Etternavn
+email=E-postadresse
+password=Passord
+passwordConfirm=Bekreft passord
+passwordNew=Nytt passord
+passwordNewConfirm=Bekreft nytt Passord
+rememberMe=Husk meg
+authenticatorCode=Engangskode
+address=Adresse
+street=Gate-/veinavn + husnummer
+locality=By
+region=Fylke
+postal_code=Postnummer
+country=Land
+emailVerified=E-postadresse bekreftet
+gssDelegationCredential=GSS legitimasjons-delegering
+
+loginTotpStep1=Installer <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> eller Google Authenticator p\u00E5 din mobiltelefon. Begge applikasjoner er tilgjengelige p\u00E5 <a href="https://play.google.com">Google Play</a> og Apple App Store.
+loginTotpStep2=\u00C5pne applikasjonen og skann strekkoden eller skriv inn koden
+loginTotpStep3=Skriv inn engangskoden fra applikasjonen og klikk send inn for \u00E5 fullf\u00F8re
+loginTotpOneTime=Engangskode
+
+oauthGrantRequest=Vil du gi disse tilgangsrettighetene?
+inResource=i
+
+emailVerifyInstruction1=En e-post med instruksjoner for \u00E5 bekrefte din e-postadresse har blitt sendt til deg.
+emailVerifyInstruction2=Ikke mottatt en bekreftelseskode i e-posten vi sendte til deg?
+emailVerifyInstruction3=for \u00E5 sende e-post p\u00E5 nytt.
+
+emailLinkIdpTitle=Lenke {0}
+emailLinkIdp1=En e-post med instruksjoner for \u00E5 koble {0} konto med din {2} konto har blitt sendt til deg.
+emailLinkIdp2=Ikke mottatt en bekreftelseskode i e-posten vi sendte til deg?
+emailLinkIdp3=for \u00E5 sende e-post p\u00E5 nytt.
+
+backToLogin=&laquo; Tilbake til innlogging
+emailInstruction=Skriv inn e-postadressen din og vi vil sende deg instruksjoner for hvordan du oppretter et nytt passord.
+
+copyCodeInstruction=Vennligst kopier denne koden og lim den inn i applikasjonen din:
+
+personalInfo=Personlig informasjon:
+role_admin=Administrator
+role_realm-admin=Administrator for sikkerhetsdomene
+role_create-realm=Opprette sikkerhetsdomene
+role_create-client=Opprette klient
+role_view-realm=Se sikkerhetsdomene
+role_view-users=Se brukere
+role_view-applications=Se applikasjoner
+role_view-clients=Se klienter
+role_view-events=Se hendelser
+role_view-identity-providers=Se identitetsleverand\u00F8rer
+role_manage-realm=Administrere sikkerhetsdomene
+role_manage-users=Administrere brukere
+role_manage-applications=Administrere applikasjoner
+role_manage-identity-providers=Administrere identitetsleverand\u00F8rer
+role_manage-clients=Administrere klienter
+role_manage-events=Administrere hendelser
+role_view-profile=Se profil
+role_manage-account=Administrere konto
+role_read-token=Lese token
+role_offline-access=Frakoblet tilgang
+role_uma_authorization=Skaffe tillatelser
+client_account=Konto
+client_security-admin-console=Sikkerthetsadministrasjonskonsoll
+client_realm-management=Sikkerhetsdomene-administrasjon
+client_broker=Broker
+
+invalidUserMessage=Ugyldig brukernavn eller passord.
+invalidEmailMessage=Ugyldig e-postadresse.
+accountDisabledMessage=Konto er deaktivert, kontakt administrator.
+accountTemporarilyDisabledMessage=Konto er midlertidig deaktivert, kontakt administrator eller pr\u00F8v p\u00E5 nytt senere.
+expiredCodeMessage=Login ble tidsavbrutt. Vennligst logg inn p\u00E5 nytt.
+
+missingFirstNameMessage=Vennligst oppgi fornavn.
+missingLastNameMessage=Vennligst oppgi etternavn.
+missingEmailMessage=Vennligst oppgi e-postadresse.
+missingUsernameMessage=Vennligst oppgi brukernavn.
+missingPasswordMessage=Vennligst oppgi passord.
+missingTotpMessage=Vennligst oppgi autentiseringskode.
+notMatchPasswordMessage=Passordene er ikke like.
+
+invalidPasswordExistingMessage=Ugyldig eksisterende passord.
+invalidPasswordConfirmMessage=Passord er ikke like.
+invalidTotpMessage=Ugyldig engangskode.
+
+usernameExistsMessage=Brukernavnet finnes allerede.
+emailExistsMessage=E-post finnes allerede.
+
+federatedIdentityExistsMessage=Bruker med {0} {1} finnes allerede. Vennligst logg inn p\u00E5 kontoadministratsjon for \u00E5 koble sammen kontoene.
+
+confirmLinkIdpTitle=Kontoen finnes allerede
+federatedIdentityConfirmLinkMessage=Bruker med {0} {1} finnes allerede. Hvordan vil du fortsette?
+federatedIdentityConfirmReauthenticateMessage=Bekreft at du er {0} for \u00E5 koble din konto med {1}
+confirmLinkIdpReviewProfile=Se over og bekreft profil
+confirmLinkIdpContinue=Legg til eksisterende konto
+
+configureTotpMessage=Du m\u00E5 sette opp en engangskode-generator for \u00E5 aktivere konto.
+updateProfileMessage=Du m\u00E5 oppdatere brukerprofilen din for \u00E5 aktivere konto.
+updatePasswordMessage=Du m\u00E5 skifte passord for \u00E5 aktivere kontoen din.
+verifyEmailMessage=Du m\u00E5 bekrefte e-postadressen din for \u00E5 aktivere konto.
+linkIdpMessage=You need to verify your email address to link your account with {0}.
+
+emailSentMessage=Du vil straks motta en e-post med ytterlige instruksjoner.
+emailSendErrorMessage=Mislyktes \u00E5 sende e-post, vennligst pr\u00F8v igjen senere.
+
+accountUpdatedMessage=Din konto har blitt oppdatert.
+accountPasswordUpdatedMessage=Ditt passord har blitt oppdatert.
+
+noAccessMessage=Ingen tilgang
+
+invalidPasswordMinLengthMessage=Ugyldig passord: minimum lengde {0}.
+invalidPasswordMinDigitsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} sifre.
+invalidPasswordMinLowerCaseCharsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} sm\u00E5 bokstaver.
+invalidPasswordMinUpperCaseCharsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} store bokstaver.
+invalidPasswordMinSpecialCharsMessage=Ugyldig passord: m\u00E5 inneholde minimum {0} spesialtegn.
+invalidPasswordNotUsernameMessage=Ugyldig passord: kan ikke v\u00E6re likt brukernavn.
+invalidPasswordRegexPatternMessage=Ugyldig passord: tilfredsstiller ikke kravene for passord-m\u00F8nster.
+invalidPasswordHistoryMessage=Ugyldig passord: kan ikke v\u00E6re likt noen av de {0} foreg\u00E5ende passordene.
+
+failedToProcessResponseMessage=Kunne ikke behandle svar
+httpsRequiredMessage=HTTPS p\u00E5krevd
+realmNotEnabledMessage=Sikkerhetsdomene er ikke aktivert
+invalidRequestMessage=Ugyldig foresp\u00F8rsel
+failedLogout=Utlogging feilet
+unknownLoginRequesterMessage=Ukjent anmoder for innlogging
+loginRequesterNotEnabledMessage=Anmoder for innlogging er ikke aktivert
+bearerOnlyMessage=Bearer-only applikasjoner har ikke lov til \u00E5 initiere innlogging via nettleser
+standardFlowDisabledMessage=Klienten har ikke lov til \u00E5 initiere innlogging via nettleser med gitt response_type. Standard flow er deaktivert for denne klienten.
+implicitFlowDisabledMessage=Klienten har ikke lov til \u00E5 initiere innlogging via nettleser med gitt response_type. Implicit flow er deaktivert for denne klienten.
+invalidRedirectUriMessage=Ugyldig redirect uri
+unsupportedNameIdFormatMessage=NameIDFormat er ikke st\u00F8ttet
+invalidRequesterMessage=Ugyldig sender av foresp\u00F8rsel
+registrationNotAllowedMessage=Registrering er ikke lov
+resetCredentialNotAllowedMessage=Tilbakestilling av innloggingsdata er ikke lov
+
+permissionNotApprovedMessage=Tillatelse ikke godkjent.
+noRelayStateInResponseMessage=Ingen relay state i svar fra identitetsleverand\u00F8r.
+insufficientPermissionMessage=Utilstrekkelige rettigheter for \u00E5 koble identiteter.
+couldNotProceedWithAuthenticationRequestMessage=Kunne ikke g\u00E5 videre med autentiseringsforesp\u00F8rsel til identitetsleverand\u00F8r.
+couldNotObtainTokenMessage=Klarte ikke \u00E5 innhente token fra identitetsleverand\u00F8r.
+unexpectedErrorRetrievingTokenMessage=Uventet feil ved henting av token fra identitetsleverand\u00F8r.
+unexpectedErrorHandlingResponseMessage=Uventet feil ved h\u00E5ndtering av svar fra identitetsleverand\u00F8r.
+identityProviderAuthenticationFailedMessage=Autentisering feilet. Kunne ikke autentisere med identitetsleverand\u00F8r.
+identityProviderDifferentUserMessage= Autentisert som {0}, men forventet \u00E5 bli identifisert som {1}
+couldNotSendAuthenticationRequestMessage=Kunne ikke sende autentiseringsforesp\u00F8rsel til identitetsleverand\u00F8r.
+unexpectedErrorHandlingRequestMessage=Uventet feil ved h\u00E5ndtering av autentiseringsforesp\u00F8rsel til identitetsleverand\u00F8r.
+invalidAccessCodeMessage=Ugyldig tilgangskode.
+sessionNotActiveMessage=Sesjonen er ikke aktiv.
+invalidCodeMessage=En feil oppstod, vennligst logg inn p\u00E5 nytt i din applikasjon.
+identityProviderUnexpectedErrorMessage=Uventet feil ved autentisering med identitetsleverand\u00F8r
+identityProviderNotFoundMessage=Kunne ikke finne en identitetsleverand\u00F8r med identifikatoren.
+identityProviderLinkSuccess=Din konto ble suksessfullt koblet med {0} konto {1}.
+staleCodeMessage=Denne siden er ikke lenger gyldig. Vennligst g\u00E5 tilbake til applikasjonen din og logg inn p\u00E5 nytt.
+realmSupportsNoCredentialsMessage=Sikkerhetsdomene st\u00F8tter ingen legitimasjonstyper.
+identityProviderNotUniqueMessage=Sikkerhetsdomene st\u00F8tter flere identitetsleverand\u00F8rer. Kunne ikke avgj\u00F8re hvilken identitetsleverand\u00F8r som burde brukes for autentisering.
+emailVerifiedMessage=Din e-postadresse har blitt verifisert.
+staleEmailVerificationLink=Lenken du klikket er utg\u00E5tt og er ikke lenger gyldig. Har du kanskje allerede bekreftet e-postadressen din?
+
+locale_ca=Catal\u00E0
+locale_de=Deutsch
+locale_en=English
+locale_es=Espa\u00F1ol
+locale_fr=Fran\u00e7ais
+locale_it=Italian
+locale_ja=\u65E5\u672C\u8A9E
+locale_no=Norsk
+locale_pt_BR=Portugu\u00EAs (Brasil)
+locale_pt-BR=Portugu\u00EAs (Brasil)
+locale_ru=\u0420\u0443\u0441\u0441\u043A\u0438\u0439
+
+backToApplication=&laquo; Tilbake til applikasjonen
+missingParameterMessage=Manglende parameter\: {0}
+clientNotFoundMessage=Klient ikke funnet.
+clientDisabledMessage=Klient deaktivert.
+invalidParameterMessage=Ugyldig parameter\: {0}
+alreadyLoggedIn=Du er allerede innlogget.
+
+p3pPolicy=CP="Dette er ikke en P3P policy!"
diff --git a/themes/src/main/resources/theme/base/login/theme.properties b/themes/src/main/resources/theme/base/login/theme.properties
index 503eda7..deb2dc9 100644
--- a/themes/src/main/resources/theme/base/login/theme.properties
+++ b/themes/src/main/resources/theme/base/login/theme.properties
@@ -1 +1 @@
-locales=ca,de,en,es,fr,it,pt-BR,ru
\ No newline at end of file
+locales=ca,de,en,es,fr,it,ja,pt-BR,ru,no
\ No newline at end of file
diff --git a/wildfly/server-subsystem/pom.xml b/wildfly/server-subsystem/pom.xml
index 5601739..05b0fc0 100755
--- a/wildfly/server-subsystem/pom.xml
+++ b/wildfly/server-subsystem/pom.xml
@@ -47,12 +47,35 @@
                         <include>**/*TestCase.java</include>
                     </includes>
                 </configuration>
-            </plugin>            
+            </plugin>        
         </plugins>
+        <filters>
+            <filter>src/main/config/default-server-subsys-config.properties</filter>
+        </filters>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <testResources>
+            <testResource>
+                <directory>src/test/resources</directory>
+                <filtering>true</filtering>
+            </testResource>
+        </testResources>
     </build>
 
     <dependencies>
         <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.wildfly.core</groupId>
             <artifactId>wildfly-controller</artifactId>
             <scope>provided</scope>
diff --git a/wildfly/server-subsystem/src/main/config/default-server-subsys-config.properties b/wildfly/server-subsystem/src/main/config/default-server-subsys-config.properties
new file mode 100644
index 0000000..2355ab0
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/config/default-server-subsys-config.properties
@@ -0,0 +1,73 @@
+# IMPORTANT: If you change this file you should also make equivalent changes
+# to src/main/resources/cli/default-keycloak-subsys-config.cli
+# The CLI file is packaged with the subsystem and extracted by the overlay distribution.
+
+keycloak.server.subsys.default.config=\
+<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">\
+   <web-context>auth</web-context>\
+    <providers>\
+        <provider>classpath:${jboss.home.dir}/providers/*</provider>\
+    </providers>\
+    <master-realm-name>master</master-realm-name>\
+    <scheduled-task-interval>900</scheduled-task-interval>\
+    <theme>\
+        <staticMaxAge>2592000</staticMaxAge>\
+        <cacheThemes>true</cacheThemes>\
+        <cacheTemplates>true</cacheTemplates>\
+        <dir>${jboss.home.dir}/themes</dir>\
+    </theme>\
+    <spi name="eventsStore">\
+        <default-provider>jpa</default-provider>\
+        <provider name="jpa" enabled="true">\
+            <properties>\
+                <property name="exclude-events" value="[&quot;REFRESH_TOKEN&quot;]"/>\
+            </properties>\
+        </provider>\
+    </spi>\
+    <spi name="realm">\
+        <default-provider>jpa</default-provider>\
+    </spi>\
+    <spi name="user">\
+        <default-provider>jpa</default-provider>\
+    </spi>\
+    <spi name="userCache">\
+        <provider name="default" enabled="true"/>\
+    </spi>\
+    <spi name="userSessionPersister">\
+        <default-provider>jpa</default-provider>\
+    </spi>\
+    <spi name="authorizationPersister">\
+        <default-provider>jpa</default-provider>\
+    </spi>\
+    <spi name="timer">\
+        <default-provider>basic</default-provider>\
+    </spi>\
+    <spi name="connectionsHttpClient">\
+        <provider name="default" enabled="true"/>\
+    </spi>\
+    <spi name="connectionsJpa">\
+        <provider name="default" enabled="true">\
+            <properties>\
+                <property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>\
+                <property name="initializeEmpty" value="true"/>\
+                <property name="migrationStrategy" value="update"/>\
+                <property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>\
+            </properties>\
+        </provider>\
+    </spi>\
+    <spi name="realmCache">\
+        <provider name="default" enabled="true"/>\
+    </spi>\
+    <spi name="connectionsInfinispan">\
+        <default-provider>default</default-provider>\
+        <provider name="default" enabled="true">\
+            <properties>\
+                <property name="cacheContainer" value="java:comp/env/infinispan/Keycloak"/>\
+            </properties>\
+        </provider>\
+    </spi>\
+    <spi name="jta-lookup">\
+        <default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>\
+        <provider name="jboss" enabled="true"/>\
+    </spi>\
+</subsystem>\
\ No newline at end of file
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/attributes/ModulesListAttributeBuilder.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/attributes/ModulesListAttributeBuilder.java
new file mode 100644
index 0000000..d47ea10
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/attributes/ModulesListAttributeBuilder.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.attributes;
+
+import org.jboss.as.controller.StringListAttributeDefinition;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ModulesListAttributeBuilder extends StringListAttributeDefinition.Builder {
+    public ModulesListAttributeBuilder() {
+        super("modules");
+        setAllowExpression(true);
+        setAllowNull(true);
+    }
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/attributes/ProvidersListAttributeBuilder.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/attributes/ProvidersListAttributeBuilder.java
new file mode 100644
index 0000000..2b4952e
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/attributes/ProvidersListAttributeBuilder.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.attributes;
+
+import org.jboss.as.controller.StringListAttributeDefinition;
+import org.jboss.dmr.ModelNode;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ProvidersListAttributeBuilder extends StringListAttributeDefinition.Builder {
+    public ProvidersListAttributeBuilder() {
+        super("providers");
+        ModelNode provider = new ModelNode();
+        provider.add("classpath:${jboss.home.dir}/providers/*");
+        this.defaultValue = provider;
+        setAllowExpression(true);
+        setAllowNull(true);
+    }
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/JsonConfigConverter.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/JsonConfigConverter.java
new file mode 100644
index 0000000..aa4d3f5
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/JsonConfigConverter.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.subsystem.server.extension;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.operations.common.Util;
+import org.jboss.dmr.ModelNode;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION;
+
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.PROVIDERS;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.MASTER_REALM_NAME;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.SCHEDULED_TASK_INTERVAL;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.CACHE_TEMPLATES;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.CACHE_THEMES;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.DEFAULT;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.DIR;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.MODULES;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.STATIC_MAX_AGE;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.WELCOME_THEME;
+
+/**
+ * Converts json representation of Keycloak config to DMR operations.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class JsonConfigConverter {
+
+    private static final List<String> NON_SPI_LIST = new ArrayList<>();
+    
+    static {
+        NON_SPI_LIST.add("providers");
+        NON_SPI_LIST.add("admin");
+        NON_SPI_LIST.add("theme");
+        NON_SPI_LIST.add("scheduled");
+    }
+
+    /**
+     * Convert keycloak-server.json to DMR operations that write to standalone.xml
+     * or domain.xml.
+     * 
+     * @param json The json representation of the config.
+     * @param subsysAddress The management model address of the keycloak-server subsystem.
+     * @return A list of DMR operations.
+     * @throws IOException If the json can not be parsed.
+     */
+    public static List<ModelNode> convertJsonConfig(String json, PathAddress subsysAddress) throws IOException {
+        List<ModelNode> list = new ArrayList<>();
+
+        JsonNode root = new ObjectMapper().readTree(json);
+
+        list.add(masterRealmName(root, subsysAddress));
+        list.add(scheduledTaskInterval(root, subsysAddress));
+        list.add(providers(root, subsysAddress));
+        list.add(theme(root, subsysAddress.append(ThemeResourceDefinition.TAG_NAME, 
+                                                ThemeResourceDefinition.RESOURCE_NAME)));
+        list.addAll(spis(root, subsysAddress));
+
+        return list;
+    }
+
+    private static ModelNode masterRealmName(JsonNode root, PathAddress addr) {
+        JsonNode targetNode = getNode(root, "admin", "realm");
+        String value = MASTER_REALM_NAME.getDefaultValue().asString();
+        if (targetNode != null) value = targetNode.asText(value);
+        
+        ModelNode op = Util.createOperation(WRITE_ATTRIBUTE_OPERATION, addr);
+        op.get("name").set(MASTER_REALM_NAME.getName());
+        op.get("value").set(value);
+        return op;
+    }
+    
+    private static ModelNode scheduledTaskInterval(JsonNode root, PathAddress addr) {
+        JsonNode targetNode = getNode(root, "scheduled", "interval");
+        Long value = SCHEDULED_TASK_INTERVAL.getDefaultValue().asLong();
+        if (targetNode != null) value = targetNode.asLong(value);
+        
+        ModelNode op = Util.createOperation(WRITE_ATTRIBUTE_OPERATION, addr);
+        op.get("name").set(SCHEDULED_TASK_INTERVAL.getName());
+        op.get("value").set(value);
+        return op;
+    }
+    
+    private static ModelNode providers(JsonNode root, PathAddress addr) {
+        JsonNode targetNode = getNode(root, "providers");
+        ModelNode value = PROVIDERS.getDefaultValue();
+        if (targetNode != null && targetNode.isArray()) {
+            value = new ModelNode();
+            for (JsonNode node : targetNode) {
+                value.add(node.asText());
+            }
+        }
+        
+        ModelNode op = Util.createOperation(WRITE_ATTRIBUTE_OPERATION, addr);
+        op.get("name").set(PROVIDERS.getName());
+        op.get("value").set(value);
+        return op;
+    }
+    
+    private static ModelNode theme(JsonNode root, PathAddress addr) {
+        JsonNode themeNode = getNode(root, "theme");
+        ModelNode op = Util.createAddOperation(addr);
+        
+        JsonNode targetNode = getNode(themeNode, "staticMaxAge");
+        Long lValue = STATIC_MAX_AGE.getDefaultValue().asLong();
+        if (targetNode != null) lValue = targetNode.asLong(lValue);
+        op.get(STATIC_MAX_AGE.getName()).set(lValue);
+
+        targetNode = getNode(themeNode, "cacheTemplates");
+        Boolean bValue = CACHE_TEMPLATES.getDefaultValue().asBoolean();
+        if (targetNode != null) bValue = targetNode.asBoolean(bValue);
+        op.get(CACHE_TEMPLATES.getName()).set(bValue);
+        
+        targetNode = getNode(themeNode, "cacheThemes");
+        bValue = CACHE_THEMES.getDefaultValue().asBoolean();
+        if (targetNode != null) bValue = targetNode.asBoolean(bValue);
+        op.get(CACHE_THEMES.getName()).set(bValue);
+        
+        targetNode = getNode(themeNode, "folder", "dir");
+        String sValue = DIR.getDefaultValue().asString();
+        if (targetNode != null) sValue = targetNode.asText(sValue);
+        op.get(DIR.getName()).set(sValue);
+        
+        targetNode = getNode(themeNode, "welcomeTheme");
+        if (targetNode != null) op.get(WELCOME_THEME.getName()).set(targetNode.asText());
+        
+        targetNode = getNode(themeNode, "default");
+        if (targetNode != null) op.get(DEFAULT.getName()).set(targetNode.asText());
+        
+        targetNode = getNode(themeNode, "module", "modules");
+        if (targetNode != null && targetNode.isArray()) {
+            op.get(MODULES.getName()).set(themeModules(targetNode));
+        }
+        
+        return op;
+    }
+    
+    private static ModelNode themeModules(JsonNode modulesNode) {
+        ModelNode modules = new ModelNode();
+        for (JsonNode node : modulesNode) {
+            modules.add(node.asText());
+        }
+        return modules;
+    }
+    
+    private static Collection<ModelNode> spis(JsonNode root, PathAddress addr) {
+        List<ModelNode> spis = new ArrayList<>();
+        
+        Iterator<String> spiIterator = root.fieldNames();
+        while (spiIterator.hasNext()) {
+            String spiName = spiIterator.next();
+            if (NON_SPI_LIST.contains(spiName)) continue;
+            
+            PathAddress spiAddr = addr.append("spi", spiName);
+            spis.addAll(spi(root, spiAddr, spiName));
+        }
+        
+        return spis;
+    }
+    
+    private static List<ModelNode> spi(JsonNode root, PathAddress spiAddr, String spiName) {
+        List<ModelNode> spiAndProviders = new ArrayList<>();
+        ModelNode op = Util.createAddOperation(spiAddr);
+        spiAndProviders.add(op);
+        
+        Iterator<String> providerIterator = root.get(spiName).fieldNames();
+        while (providerIterator.hasNext()) {
+            String providerName = providerIterator.next();
+            if ("provider".equals(providerName)) {
+                op.get(SpiResourceDefinition.DEFAULT_PROVIDER.getName()).set(getNode(root, spiName, "provider").asText());
+            } else {
+                PathAddress providerAddr = spiAddr.append("provider", providerName);
+                spiAndProviders.add(spiProvider(getNode(root, spiName, providerName), providerAddr));
+            }
+        }
+        
+        return spiAndProviders;
+    }
+    
+    private static ModelNode spiProvider(JsonNode providerNode, PathAddress providerAddr) {
+        ModelNode op = Util.createAddOperation(providerAddr);
+        
+        ModelNode properties = new ModelNode();
+        
+        Iterator<String> propNames = providerNode.fieldNames();
+        while (propNames.hasNext()) {
+            String propName = propNames.next();
+            
+            if ("enabled".equals(propName)) {
+                op.get(ProviderResourceDefinition.ENABLED.getName()).set(providerNode.get(propName).asBoolean());
+            } else {
+                if (providerNode.get(propName).isArray()) {
+                    properties.get(propName).set(makeArrayText(providerNode.get(propName)));
+                } else {
+                    properties.get(propName).set(providerNode.get(propName).asText());
+                }
+            }
+        }
+        
+        if (properties.isDefined() && !properties.asPropertyList().isEmpty()) {
+            op.get("properties").set(properties);
+        }
+        
+        if (!op.hasDefined(ProviderResourceDefinition.ENABLED.getName())) {
+            op.get(ProviderResourceDefinition.ENABLED.getName()).set(ProviderResourceDefinition.ENABLED.getDefaultValue());
+        }
+        
+        return op;
+    }
+    
+    private static String makeArrayText(JsonNode arrayNode) {
+        StringBuilder builder = new StringBuilder("[");
+        
+        Iterator<JsonNode> nodes = arrayNode.iterator();
+        while (nodes.hasNext()) {
+            JsonNode node = nodes.next();
+            builder.append("\"");
+            builder.append(node.asText());
+            builder.append("\"");
+            if (nodes.hasNext()) builder.append(",");
+        }
+        builder.append("]");
+        
+        return builder.toString();
+    }
+    
+    private static JsonNode getNode(JsonNode root, String... path) {
+        if (root == null) {
+            return null;
+        }
+        JsonNode n = root;
+        for (String p : path) {
+            n = n.get(p);
+            if (n == null) {
+                return null;
+            }
+        }
+        return n;
+    }
+
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java
index 03a2fe2..0eec2ee 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakAdapterConfigService.java
@@ -16,9 +16,15 @@
  */
 package org.keycloak.subsystem.server.extension;
 
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.PathElement;
+import org.jboss.dmr.ModelNode;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
+import org.jboss.dmr.Property;
+
 /**
  * This service keeps track of the entire Keycloak management model so as to provide
- * adapter configuration to each deployment at deploy time.
+ * configuration to the Keycloak Server.
  *
  * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
  */
@@ -27,6 +33,8 @@ public final class KeycloakAdapterConfigService {
     static final KeycloakAdapterConfigService INSTANCE = new KeycloakAdapterConfigService();
 
     static final String DEPLOYMENT_NAME = "keycloak-server.war";
+    
+    static ModelNode fullConfig = new ModelNode();
 
     private String webContext;
 
@@ -34,6 +42,127 @@ public final class KeycloakAdapterConfigService {
     private KeycloakAdapterConfigService() {
     }
 
+    void updateConfig(ModelNode operation, ModelNode config) {
+        PathAddress address = PathAddress.pathAddress(operation.get(ADDRESS));
+        address = address.subAddress(1); // remove root (subsystem=keycloak-server)
+        
+        ModelNode newConfig = fullConfig.clone();
+        ModelNode subNode = newConfig;
+        for (PathElement pathElement : address) {
+            subNode = subNode.get(pathElement.getKey(), pathElement.getValue());
+        }
+        
+        subNode.set(config.clone());
+        
+        // remove undefined properties
+        for (Property prop : subNode.asPropertyList()) {
+            if (!prop.getValue().isDefined()) {
+                subNode.remove(prop.getName());
+            }
+        }
+        
+        fullConfig = newConfig;
+    }
+    
+    ModelNode getConfig() {
+        ModelNode copy = fullConfig.clone();
+        //System.out.println("******** BEFORE *************");
+        //System.out.println(copy);
+        //System.out.println("*****************************");
+        copy.remove("web-context");
+        massageScheduledTaskInterval(copy);
+        massageMasterRealm(copy);
+        massageTheme(copy);
+        massageSpis(copy);
+        //System.out.println("******** JSON *************");
+        //System.out.println(copy.resolve().toJSONString(false));
+        //System.out.println("**********************");
+        return copy;
+    }
+    
+    // The "massage" methods rearrange the model so that everything will
+    // be where the Keycloak server's Config interface expects it to be.
+    
+    private void massageScheduledTaskInterval(ModelNode copy) {
+        if (!copy.hasDefined("scheduled-task-intervale")) return;
+        ModelNode taskInterval = copy.remove("scheduled-task-interval");
+        copy.get("scheduled", "interval").set(taskInterval);
+    }
+    
+    private void massageMasterRealm(ModelNode copy) {
+        if (!copy.hasDefined("master-realm-name")) return;
+        ModelNode master = copy.remove("master-realm-name");
+        copy.get("admin", "realm").set(master);
+    }
+    
+    private void massageTheme(ModelNode copy) {
+        if (!copy.hasDefined("theme")) return;
+        if (!copy.get("theme").hasDefined("defaults")) return;
+        
+        ModelNode themeDefaults = copy.get("theme", "defaults");
+        copy.get("theme").set(themeDefaults);
+        
+        if (copy.has("theme", "dir")) {
+            ModelNode dir = copy.get("theme", "dir");
+            copy.get("theme", "folder", "dir").set(dir);
+            copy.get("theme").remove("dir");
+        }
+        
+        if (copy.has("theme", "modules")) {
+            ModelNode modules = copy.get("theme").remove("modules");
+            copy.get("theme", "module", "modules").set(modules);
+        }
+    }
+    
+    private void massageSpis(ModelNode copy) {
+        if (!copy.hasDefined("spi")) return;
+        ModelNode spis = copy.remove("spi");
+        
+        for (Property prop : spis.asPropertyList()) {
+            ModelNode spi = prop.getValue();
+            
+            if (spi.has("provider")) {
+                massageProviders(spi);
+            }
+            
+            if (spi.has("default-provider")) {
+                ModelNode defaultProvider = spi.remove("default-provider");
+                spi.get("provider").set(defaultProvider);
+            }
+            
+            copy.get(prop.getName()).set(spi);
+        }
+    }
+    
+    private void massageProviders(ModelNode spi) {
+        if (!spi.hasDefined("provider")) return;
+        ModelNode providers = spi.remove("provider");
+        for (Property prop : providers.asPropertyList()) {
+            ModelNode provider = prop.getValue();
+            if (provider.has("properties")) {
+                massageProviderProps(provider);
+            }
+            spi.get(prop.getName()).set(provider);
+        }
+    }
+    
+    private void massageProviderProps(ModelNode provider) {
+        if (!provider.hasDefined("properties")) return;
+        ModelNode providerProps = provider.remove("properties");
+        for (Property prop : providerProps.asPropertyList()) {
+            ModelNode value = prop.getValue();
+            if (isArray(value.asString().trim())) {
+                provider.get(prop.getName()).set(ModelNode.fromString(value.asString()).asList());
+            } else {
+                provider.get(prop.getName()).set(value);
+            }
+        }
+    }
+    
+    private boolean isArray(String value) {
+        return value.startsWith("[") && value.endsWith("]");
+    }
+    
     void setWebContext(String webContext) {
         this.webContext = webContext;
     }
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java
index c6a3cdb..bdfe47c 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakExtension.java
@@ -26,6 +26,7 @@ import org.jboss.as.controller.descriptions.StandardResourceDescriptionResolver;
 import org.jboss.as.controller.parsing.ExtensionParsingContext;
 
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
 import static org.keycloak.subsystem.server.logging.KeycloakLogger.ROOT_LOGGER;
 
 
@@ -44,6 +45,10 @@ public class KeycloakExtension implements Extension {
     private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
     private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
     private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1,1,0);
+    
+    static final ThemeResourceDefinition THEME_DEFINITION = new ThemeResourceDefinition();
+    static final SpiResourceDefinition SPI_DEFINITION = new SpiResourceDefinition();
+    static final ProviderResourceDefinition PROVIDER_DEFINITION = new ProviderResourceDefinition();
 
     static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
         StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
@@ -69,7 +74,11 @@ public class KeycloakExtension implements Extension {
         ROOT_LOGGER.debug("Activating Keycloak Extension");
         final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, MGMT_API_VERSION);
 
-        subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
+        ManagementResourceRegistration subsystemRegistration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
+        subsystemRegistration.registerSubModel(THEME_DEFINITION);
+        ManagementResourceRegistration spiRegistration = subsystemRegistration.registerSubModel(SPI_DEFINITION);
+        spiRegistration.registerSubModel(PROVIDER_DEFINITION);
+        
         subsystem.registerXMLElementWriter(PARSER);
     }
 }
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
index f99cab3..1bc2211 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakServerDeploymentProcessor.java
@@ -16,41 +16,78 @@
  */
 package org.keycloak.subsystem.server.extension;
 
+import java.util.ArrayList;
+import java.util.List;
 import org.jboss.as.ee.component.EEModuleDescription;
 import org.jboss.as.server.deployment.DeploymentPhaseContext;
 import org.jboss.as.server.deployment.DeploymentUnit;
 import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
+import org.jboss.as.web.common.WarMetaData;
+import org.jboss.metadata.javaee.spec.ParamValueMetaData;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
 import org.jboss.msc.service.ServiceName;
 import org.jboss.msc.service.ServiceTarget;
 
 /**
- * DUP responsible for setting the web context of a Keycloak auth server.
+ * DUP responsible for setting the web context of a Keycloak auth server and
+ * passing the Keycloak configuration to the Keycloak server.
  *
  * @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
  */
 public class KeycloakServerDeploymentProcessor implements DeploymentUnitProcessor {
 
+    // This param name is defined again in Keycloak Services class
+    // org.keycloak.services.resources.KeycloakApplication.  We have this value in
+    // two places to avoid dependency between Keycloak Subsystem and Keyclaok Services module.
+    public static final String KEYCLOAK_CONFIG_PARAM_NAME = "org.keycloak.server-subsystem.Config";
+    
     private static final ServiceName cacheContainerService = ServiceName.of("jboss", "infinispan", "keycloak");
-
+    
     @Override
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
-        KeycloakAdapterConfigService config = KeycloakAdapterConfigService.INSTANCE;
+        KeycloakAdapterConfigService configService = KeycloakAdapterConfigService.INSTANCE;
         String deploymentName = deploymentUnit.getName();
 
-        if (!config.isKeycloakServerDeployment(deploymentName)) {
+        if (!configService.isKeycloakServerDeployment(deploymentName)) {
             return;
         }
 
         final EEModuleDescription description = deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
-        String webContext = config.getWebContext();
+        String webContext = configService.getWebContext();
         if (webContext == null) {
             throw new DeploymentUnitProcessingException("Can't determine web context/module for Keycloak Server");
         }
         description.setModuleName(webContext);
 
         addInfinispanCaches(phaseContext);
+        addConfiguration(deploymentUnit, configService);
+    }
+    
+    private void addConfiguration(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService configService) throws DeploymentUnitProcessingException {
+        WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+        if (warMetaData == null) {
+            throw new DeploymentUnitProcessingException("WarMetaData not found for KeycloakServer.");
+        }
+        
+        JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+        if (webMetaData == null) {
+            webMetaData = new JBossWebMetaData();
+            warMetaData.setMergedJBossWebMetaData(webMetaData);
+        }
+
+        List<ParamValueMetaData> contextParams = webMetaData.getContextParams();
+        if (contextParams == null) {
+            contextParams = new ArrayList<ParamValueMetaData>();
+        }
+
+        ParamValueMetaData param = new ParamValueMetaData();
+        param.setParamName(KEYCLOAK_CONFIG_PARAM_NAME);
+        param.setParamValue(configService.getConfig().toString());
+        contextParams.add(param);
+
+        webMetaData.setContextParams(contextParams);
     }
 
     private void addInfinispanCaches(DeploymentPhaseContext context) {
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java
index 3c6dc34..6d75e28 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemAdd.java
@@ -62,9 +62,10 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
         }, OperationContext.Stage.RUNTIME);
     }
 
-    protected void populateModel(final OperationContext context, final ModelNode operation, final Resource resource) throws  OperationFailedException {
+    @Override
+    protected void populateModel(final OperationContext context, final ModelNode operation, final Resource resource) throws OperationFailedException {
         ModelNode model = resource.getModel();
-
+        
         // set attribute values from parsed model
         for (AttributeDefinition attrDef : ALL_ATTRIBUTES) {
             attrDef.validateAndSet(operation, model);
@@ -89,5 +90,7 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
         ServerUtil serverUtil = new ServerUtil(operation);
         serverUtil.addStepToUploadServerWar(context);
         KeycloakAdapterConfigService.INSTANCE.setWebContext(webContext);
+        
+        KeycloakAdapterConfigService.INSTANCE.updateConfig(operation, model);
     }
 }
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java
index 6fcee7b..3dc4917 100644
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemDefinition.java
@@ -29,6 +29,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.jboss.as.controller.StringListAttributeDefinition;
+import org.keycloak.subsystem.server.attributes.ProvidersListAttributeBuilder;
 
 /**
  * Definition of subsystem=keycloak-server.
@@ -44,15 +46,34 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
             .setRestartAllServices()
             .build();
 
-    static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
+    static final StringListAttributeDefinition PROVIDERS = new ProvidersListAttributeBuilder().build();
+    
+    static final SimpleAttributeDefinition MASTER_REALM_NAME =
+        new SimpleAttributeDefinitionBuilder("master-realm-name", ModelType.STRING, true)
+            .setAllowExpression(true)
+            .setDefaultValue(new ModelNode("master"))
+            .setRestartAllServices()
+            .build();
+    
+    static final SimpleAttributeDefinition SCHEDULED_TASK_INTERVAL =
+        new SimpleAttributeDefinitionBuilder("scheduled-task-interval", ModelType.LONG, true)
+            .setAllowExpression(true)
+            .setDefaultValue(new ModelNode("900"))
+            .setRestartAllServices()
+            .build();
+    
+    static final List<AttributeDefinition> ALL_ATTRIBUTES = new ArrayList<AttributeDefinition>();
 
     static {
         ALL_ATTRIBUTES.add(WEB_CONTEXT);
+        ALL_ATTRIBUTES.add(PROVIDERS);
+        ALL_ATTRIBUTES.add(MASTER_REALM_NAME);
+        ALL_ATTRIBUTES.add(SCHEDULED_TASK_INTERVAL);
     }
 
-    private static final Map<String, SimpleAttributeDefinition> DEFINITION_LOOKUP = new HashMap<String, SimpleAttributeDefinition>();
+    private static final Map<String, AttributeDefinition> DEFINITION_LOOKUP = new HashMap<String, AttributeDefinition>();
     static {
-        for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
+        for (AttributeDefinition def : ALL_ATTRIBUTES) {
             DEFINITION_LOOKUP.put(def.getXmlName(), def);
         }
     }
@@ -71,6 +92,7 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
     public void registerOperations(ManagementResourceRegistration resourceRegistration) {
         super.registerOperations(resourceRegistration);
         resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+        resourceRegistration.registerOperationHandler(MigrateJsonOperation.DEFINITION, new MigrateJsonOperation());
     }
 
     @Override
@@ -81,7 +103,7 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
         }
     }
 
-    public static SimpleAttributeDefinition lookup(String name) {
+    public static AttributeDefinition lookup(String name) {
         return DEFINITION_LOOKUP.get(name);
     }
 }
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java
index 6db6e57..0f4ea8c 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemParser.java
@@ -29,9 +29,26 @@ import org.jboss.staxmapper.XMLExtendedStreamWriter;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import java.util.List;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.PropertiesAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
+import org.jboss.dmr.Property;
 
 import static org.keycloak.subsystem.server.extension.KeycloakExtension.PATH_SUBSYSTEM;
 import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.WEB_CONTEXT;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.PROVIDERS;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.MASTER_REALM_NAME;
+import static org.keycloak.subsystem.server.extension.KeycloakSubsystemDefinition.SCHEDULED_TASK_INTERVAL;
+
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.MODULES;
+
+import static org.keycloak.subsystem.server.extension.SpiResourceDefinition.DEFAULT_PROVIDER;
+
+import static org.keycloak.subsystem.server.extension.ProviderResourceDefinition.ENABLED;
+import static org.keycloak.subsystem.server.extension.ProviderResourceDefinition.PROPERTIES;
 
 /**
  * The subsystem parser, which uses stax to read and write to and from xml
@@ -51,12 +68,116 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
         while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
             if (reader.getLocalName().equals(WEB_CONTEXT.getXmlName())) {
                 WEB_CONTEXT.parseAndSetParameter(reader.getElementText(), addKeycloakSub, reader);
+            } else if (reader.getLocalName().equals(PROVIDERS.getXmlName())) {
+                readProviders(reader, addKeycloakSub);
+            } else if (reader.getLocalName().equals(MASTER_REALM_NAME.getXmlName())) {
+                MASTER_REALM_NAME.parseAndSetParameter(reader.getElementText(), addKeycloakSub, reader);
+            } else if (reader.getLocalName().equals(SCHEDULED_TASK_INTERVAL.getXmlName())) {
+                SCHEDULED_TASK_INTERVAL.parseAndSetParameter(reader.getElementText(), addKeycloakSub, reader);
+            } else if (reader.getLocalName().equals(ThemeResourceDefinition.TAG_NAME)) {
+                readTheme(list, reader);
+            } else if (reader.getLocalName().equals(SpiResourceDefinition.TAG_NAME)) {
+                readSpi(list, reader);
             } else {
                 throw new XMLStreamException("Unknown keycloak-server subsystem tag: " + reader.getLocalName());
             }
         }
     }
-
+    
+    private void readProviders(final XMLExtendedStreamReader reader, ModelNode addKeycloakSub) throws XMLStreamException {
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            PROVIDERS.parseAndAddParameterElement(reader.getElementText(),addKeycloakSub, reader);
+        }
+    }
+    
+    private void readTheme(final List<ModelNode> list, final XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode addThemeDefaults = new ModelNode();
+        addThemeDefaults.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
+        PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
+                                                   PathElement.pathElement(ThemeResourceDefinition.TAG_NAME, ThemeResourceDefinition.RESOURCE_NAME));
+        addThemeDefaults.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
+        list.add(addThemeDefaults);
+        
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (MODULES.getName().equals(tagName)) {
+                readModules(reader, addThemeDefaults);
+                continue;
+            }
+            
+            SimpleAttributeDefinition def = KeycloakExtension.THEME_DEFINITION.lookup(tagName);
+            if (def == null) throw new XMLStreamException("Unknown theme tag " + tagName);
+            def.parseAndSetParameter(reader.getElementText(), addThemeDefaults, reader);
+        }
+    }
+    
+    private void readModules(final XMLExtendedStreamReader reader, ModelNode addThemeDefaults) throws XMLStreamException {
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            MODULES.parseAndAddParameterElement(reader.getElementText(),addThemeDefaults, reader);
+        }
+    }
+    
+    private void readSpi(final List<ModelNode> list, final XMLExtendedStreamReader reader) throws XMLStreamException {
+        String spiName = ParseUtils.requireAttributes(reader, "name")[0];
+        ModelNode addSpi = new ModelNode();
+        addSpi.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
+        PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
+                                                   PathElement.pathElement(SpiResourceDefinition.TAG_NAME, spiName));
+        addSpi.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
+        list.add(addSpi);
+        
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            if (reader.getLocalName().equals(DEFAULT_PROVIDER.getXmlName())) {
+                DEFAULT_PROVIDER.parseAndSetParameter(reader.getElementText(), addSpi, reader);
+            } else if (reader.getLocalName().equals(ProviderResourceDefinition.TAG_NAME)) {
+                readProvider(list, spiName, reader);
+            }
+        }
+    }
+    
+    private void readProvider(final List<ModelNode> list, String spiName, final XMLExtendedStreamReader reader) throws XMLStreamException {
+        String[] attributes = ParseUtils.requireAttributes(reader, "name", ENABLED.getXmlName());
+        String providerName = attributes[0];
+        String enabled = attributes[1];
+        
+        ModelNode addProvider = new ModelNode();
+        addProvider.get(ModelDescriptionConstants.OP).set(ModelDescriptionConstants.ADD);
+        PathAddress addr = PathAddress.pathAddress(PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakExtension.SUBSYSTEM_NAME),
+                                                   PathElement.pathElement(SpiResourceDefinition.TAG_NAME, spiName),
+                                                   PathElement.pathElement(ProviderResourceDefinition.TAG_NAME, providerName));
+        addProvider.get(ModelDescriptionConstants.OP_ADDR).set(addr.toModelNode());
+        addProvider.get(ENABLED.getName()).set(Boolean.valueOf(enabled));
+        list.add(addProvider);
+        
+        while (nextTag(reader) != END_ELEMENT) {
+            if (reader.getLocalName().equals(PROPERTIES.getXmlName())) {
+                readProperties(PROPERTIES, addProvider, reader);
+            }
+        }
+    }
+    
+    private void readProperties(final PropertiesAttributeDefinition attrDef, ModelNode addOp, final XMLExtendedStreamReader reader) throws XMLStreamException {
+        while (nextTag(reader) != END_ELEMENT) {
+        int attrCount = reader.getAttributeCount();
+            if (attrCount != 2) throw new XMLStreamException("Property must have only two attributes");
+            String name = "";
+            String value = "";
+            for (int i=0 ; i < 2; i++) {
+                String attrName = reader.getAttributeLocalName(i);
+                String attrValue = reader.getAttributeValue(i);
+                if (attrName.equals("name")) {
+                    name = attrValue;
+                } else if (attrName.equals("value")) {
+                    value = attrValue;
+                } else {
+                    throw new XMLStreamException("Property can only have attributes named 'name' and 'value'");
+                }
+            }
+            attrDef.parseAndAddParameterElement(name, value, addOp, reader);
+        nextTag(reader);
+        }
+            }
+        
     // used for debugging
     private int nextTag(XMLExtendedStreamReader reader) throws XMLStreamException {
         return reader.nextTag();
@@ -69,9 +190,64 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
     public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
         context.startSubsystemElement(KeycloakExtension.NAMESPACE, false);
         writeWebContext(writer, context);
+        writeList(writer, context.getModelNode(), PROVIDERS, "provider");
+        writeAdmin(writer, context);
+        writeScheduledTaskInterval(writer, context);
+        writeThemeDefaults(writer, context);
+        writeSpis(writer, context);
+        writer.writeEndElement();
+    }
+    
+    private void writeThemeDefaults(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
+        if (!context.getModelNode().get(ThemeResourceDefinition.TAG_NAME).isDefined()) {
+            return;
+        }
+        
+        writer.writeStartElement(ThemeResourceDefinition.TAG_NAME);
+        ModelNode themeElements = context.getModelNode().get(ThemeResourceDefinition.TAG_NAME, ThemeResourceDefinition.RESOURCE_NAME);
+        for (AttributeDefinition def : ThemeResourceDefinition.ALL_ATTRIBUTES) {
+            if (themeElements.hasDefined(def.getName())) {
+                if (def == MODULES) {
+                    ModelNode themeContext = context.getModelNode().get("theme", "defaults");
+                    writeList(writer, themeContext, def, "module");
+                } else {
+                    def.marshallAsElement(themeElements, writer);
+                }
+            }
+        }
         writer.writeEndElement();
     }
 
+    private void writeSpis(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
+        if (!context.getModelNode().get(SpiResourceDefinition.TAG_NAME).isDefined()) {
+            return;
+        }
+        
+        for (Property spi : context.getModelNode().get(SpiResourceDefinition.TAG_NAME).asPropertyList()) {
+            writer.writeStartElement(SpiResourceDefinition.TAG_NAME);
+            writer.writeAttribute("name", spi.getName());
+            ModelNode spiElements = spi.getValue();
+            DEFAULT_PROVIDER.marshallAsElement(spiElements, writer);
+            writeProviders(writer, spiElements);
+            writer.writeEndElement();
+        }
+    }
+    
+    private void writeProviders(XMLExtendedStreamWriter writer, ModelNode spiElements) throws XMLStreamException {
+        if (!spiElements.get(ProviderResourceDefinition.TAG_NAME).isDefined()) {
+            return;
+        }
+        
+        for (Property provider : spiElements.get(ProviderResourceDefinition.TAG_NAME).asPropertyList()) {
+            writer.writeStartElement(ProviderResourceDefinition.TAG_NAME);
+            writer.writeAttribute("name", provider.getName());
+            ModelNode providerElements = provider.getValue();
+            ENABLED.marshallAsAttribute(providerElements, writer);
+            PROPERTIES.marshallAsElement(providerElements, writer);
+            writer.writeEndElement();
+        }
+    }
+    
     private void writeWebContext(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
         if (!context.getModelNode().get(WEB_CONTEXT.getName()).isDefined()) {
             return;
@@ -79,4 +255,36 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
 
         WEB_CONTEXT.marshallAsElement(context.getModelNode(), writer);
     }
-}
+    
+    private void writeAdmin(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
+        if (!context.getModelNode().get(MASTER_REALM_NAME.getName()).isDefined()) {
+            return;
+        }
+
+        MASTER_REALM_NAME.marshallAsElement(context.getModelNode(), writer);
+    }
+    
+    private void writeScheduledTaskInterval(XMLExtendedStreamWriter writer, SubsystemMarshallingContext context) throws XMLStreamException {
+        if (!context.getModelNode().get(SCHEDULED_TASK_INTERVAL.getName()).isDefined()) {
+            return;
+        }
+
+        SCHEDULED_TASK_INTERVAL.marshallAsElement(context.getModelNode(), writer);
+    }
+    
+    private void writeList(XMLExtendedStreamWriter writer, ModelNode context, AttributeDefinition def, String elementName) throws XMLStreamException {
+        if (!context.get(def.getName()).isDefined()) {
+            return;
+        }
+
+        writer.writeStartElement(def.getXmlName());
+        ModelNode modules = context.get(def.getName());
+        for (ModelNode module : modules.asList()) {
+            writer.writeStartElement(elementName);
+            writer.writeCharacters(module.asString());
+            writer.writeEndElement();
+        }
+        writer.writeEndElement();
+    }
+    
+}
\ No newline at end of file
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java
index 8469198..3304616 100755
--- a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/KeycloakSubsystemWriteAttributeHandler.java
@@ -17,7 +17,6 @@
 package org.keycloak.subsystem.server.extension;
 
 import org.jboss.as.controller.AttributeDefinition;
-import org.jboss.as.controller.SimpleAttributeDefinition;
 
 import java.util.List;
 import org.jboss.as.controller.ModelOnlyWriteAttributeHandler;
@@ -33,7 +32,7 @@ import org.jboss.dmr.ModelNode;
  */
 public class KeycloakSubsystemWriteAttributeHandler extends ModelOnlyWriteAttributeHandler { //extends ReloadRequiredWriteAttributeHandler {
 
-    public KeycloakSubsystemWriteAttributeHandler(List<SimpleAttributeDefinition> definitions) {
+    public KeycloakSubsystemWriteAttributeHandler(List<AttributeDefinition> definitions) {
         this(definitions.toArray(new AttributeDefinition[definitions.size()]));
     }
 
@@ -59,7 +58,7 @@ public class KeycloakSubsystemWriteAttributeHandler extends ModelOnlyWriteAttrib
     }
 
     private boolean attribNotChanging(String attributeName, ModelNode newValue, ModelNode oldValue) {
-        SimpleAttributeDefinition attribDef = KeycloakSubsystemDefinition.lookup(attributeName);
+        AttributeDefinition attribDef = KeycloakSubsystemDefinition.lookup(attributeName);
         if (!oldValue.isDefined()) {
             oldValue = attribDef.getDefaultValue();
         }
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/MigrateJsonOperation.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/MigrateJsonOperation.java
new file mode 100644
index 0000000..92c229d
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/MigrateJsonOperation.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationDefinition;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
+
+/**
+ * This operation provides a migration path from keycloak-server.json to
+ * standalone.xml or domain.xml.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class MigrateJsonOperation implements OperationStepHandler {
+    public static final String OPERATION_NAME = "migrate-json";
+    
+    private static final String CONFIG_DIR = System.getProperty("jboss.server.config.dir");
+    private static final Path DEFAULT_CONFIG_FILE = Paths.get(CONFIG_DIR, "keycloak-server.json");
+
+    private static final AttributeDefinition FILE_ATTRIBUTE = SimpleAttributeDefinitionBuilder.create("file", ModelType.BYTES, true).build();
+    public static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OPERATION_NAME, KeycloakExtension.getResourceDescriptionResolver())
+            .setRuntimeOnly()
+            .setReadOnly()
+            .setReplyType(ModelType.STRING)
+            .setParameters(FILE_ATTRIBUTE)
+            .build();
+
+    private String localConfig() throws IOException {
+        if (Files.notExists(DEFAULT_CONFIG_FILE)) return null;
+        return new String(Files.readAllBytes(DEFAULT_CONFIG_FILE));
+    }
+    
+    private String readConfig(ModelNode operation) throws IOException {
+        ModelNode file = operation.get(FILE_ATTRIBUTE.getName());
+        if (file.isDefined() && file.asBytes().length > 0) {
+            return new String(file.asBytes());
+        }
+        
+        String localConfig = localConfig();
+        if (localConfig != null) return localConfig;
+        
+        throw new IOException("Can not find json file to migrate");
+    }
+    
+    @Override
+    public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
+        List<ModelNode> ops = null;
+        try {
+            PathAddress currentAddr = context.getCurrentAddress();
+            ops = JsonConfigConverter.convertJsonConfig(readConfig(operation), currentAddr);
+        } catch (IOException ioe) {
+            throw new OperationFailedException(ioe);
+        }
+         
+        for (ModelNode op : ops) {
+            PathAddress addr = PathAddress.pathAddress(op.get(ADDRESS));
+            String opName = op.get(OP).asString();
+            context.addStep(op, 
+                            context.getRootResourceRegistration().getOperationHandler(addr, opName), 
+                            OperationContext.Stage.MODEL);
+        }
+        
+        context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
+    }
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceAddHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceAddHandler.java
new file mode 100644
index 0000000..7db883c
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceAddHandler.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationFailedException;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
+import org.jboss.dmr.ModelNode;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ProviderResourceAddHandler extends AbstractAddStepHandler {
+
+    public static ProviderResourceAddHandler INSTANCE = new ProviderResourceAddHandler();
+
+    private ProviderResourceAddHandler() {
+    }
+
+    @Override
+    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
+        // TODO: localize exception. get id number
+        if (!operation.get(OP).asString().equals(ADD)) {
+            throw new OperationFailedException("Unexpected operation for add SPI. operation=" + operation.toString());
+        }
+
+        ProviderResourceDefinition.ENABLED.validateAndSet(operation, model);
+        ProviderResourceDefinition.PROPERTIES.validateAndSet(operation, model);
+        
+        KeycloakAdapterConfigService.INSTANCE.updateConfig(operation, model);
+    }
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceDefinition.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceDefinition.java
new file mode 100644
index 0000000..68ba9bb
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceDefinition.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.PropertiesAttributeDefinition;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ProviderResourceDefinition extends SimpleResourceDefinition {
+
+    public static final String TAG_NAME = "provider";
+    
+    protected static final SimpleAttributeDefinition ENABLED =
+            new SimpleAttributeDefinitionBuilder("enabled", ModelType.BOOLEAN, true)
+                    .setAllowExpression(true)
+                    .setDefaultValue(new ModelNode(true))
+                    .setAllowNull(false)
+                    .setRestartAllServices()
+                    .build();
+    
+    static final PropertiesAttributeDefinition PROPERTIES =
+            new PropertiesAttributeDefinition.Builder("properties", true)
+            .setRestartAllServices()
+            .setAllowExpression(true)
+            .build();
+    
+    protected static final ReloadRequiredWriteAttributeHandler WRITE_ATTR_HANDLER = new ReloadRequiredWriteAttributeHandler(ENABLED);
+    
+    protected ProviderResourceDefinition() {
+        super(PathElement.pathElement(TAG_NAME),
+            KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
+            ProviderResourceAddHandler.INSTANCE,
+            ProviderResourceRemoveHandler.INSTANCE
+        );
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+        resourceRegistration.registerReadWriteAttribute(ENABLED, null, WRITE_ATTR_HANDLER);
+        resourceRegistration.registerReadWriteAttribute(PROPERTIES, null, WRITE_ATTR_HANDLER);
+    }
+    
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceRemoveHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceRemoveHandler.java
new file mode 100644
index 0000000..21d8217
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ProviderResourceRemoveHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.AbstractRemoveStepHandler;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ProviderResourceRemoveHandler extends AbstractRemoveStepHandler {
+    
+    public static ProviderResourceRemoveHandler INSTANCE = new ProviderResourceRemoveHandler();
+    
+    private ProviderResourceRemoveHandler() {}
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceAddHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceAddHandler.java
new file mode 100644
index 0000000..3d41791
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceAddHandler.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationFailedException;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
+import org.jboss.dmr.ModelNode;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class SpiResourceAddHandler extends AbstractAddStepHandler {
+
+    public static SpiResourceAddHandler INSTANCE = new SpiResourceAddHandler();
+    
+    private SpiResourceAddHandler() {}
+    
+    @Override
+    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
+        // TODO: localize exception. get id number
+        if (!operation.get(OP).asString().equals(ADD)) {
+            throw new OperationFailedException("Unexpected operation for add SPI. operation=" + operation.toString());
+        }
+
+        SpiResourceDefinition.DEFAULT_PROVIDER.validateAndSet(operation, model);
+        
+        KeycloakAdapterConfigService.INSTANCE.updateConfig(operation, model);
+    }
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceDefinition.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceDefinition.java
new file mode 100644
index 0000000..db15ba4
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceDefinition.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class SpiResourceDefinition extends SimpleResourceDefinition {
+
+    public static final String TAG_NAME = "spi";
+    
+    protected static final SimpleAttributeDefinition DEFAULT_PROVIDER =
+            new SimpleAttributeDefinitionBuilder("default-provider", ModelType.STRING, true)
+                    .setAllowExpression(true)
+                    .setRestartAllServices()
+                    .build();
+    
+    protected static final ReloadRequiredWriteAttributeHandler WRITE_ATTR_HANDLER = new ReloadRequiredWriteAttributeHandler(DEFAULT_PROVIDER);
+    
+    protected SpiResourceDefinition() {
+        super(PathElement.pathElement(TAG_NAME),
+            KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
+            SpiResourceAddHandler.INSTANCE,
+            SpiResourceRemoveHandler.INSTANCE
+        );
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+        resourceRegistration.registerReadWriteAttribute(DEFAULT_PROVIDER, null, WRITE_ATTR_HANDLER);
+    }
+    
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceRemoveHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceRemoveHandler.java
new file mode 100644
index 0000000..468a40a
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/SpiResourceRemoveHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.AbstractRemoveStepHandler;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class SpiResourceRemoveHandler extends AbstractRemoveStepHandler {
+    
+    public static SpiResourceRemoveHandler INSTANCE = new SpiResourceRemoveHandler();
+    
+    private SpiResourceRemoveHandler() {}
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceAddHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceAddHandler.java
new file mode 100644
index 0000000..b955101
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceAddHandler.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.PathElement;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
+import org.jboss.dmr.ModelNode;
+import static org.keycloak.subsystem.server.extension.ThemeResourceDefinition.ALL_ATTRIBUTES;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ThemeResourceAddHandler extends AbstractAddStepHandler {
+
+    public static ThemeResourceAddHandler INSTANCE = new ThemeResourceAddHandler();
+    
+    private ThemeResourceAddHandler() {}
+    
+    @Override
+    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
+        // TODO: localize exception. get id number
+        if (!operation.get(OP).asString().equals(ADD)) {
+            throw new OperationFailedException("Unexpected operation for add Theme. operation=" + operation.toString());
+        }
+        
+        PathAddress address = PathAddress.pathAddress(operation.get(ADDRESS));
+        PathElement last = address.getLastElement();
+        if (!last.getValue().equals(ThemeResourceDefinition.RESOURCE_NAME)) {
+            throw new OperationFailedException("Theme resource with name " + last.getValue() + " not allowed.");
+        }
+
+        for (AttributeDefinition def : ALL_ATTRIBUTES) {
+            def.validateAndSet(operation, model);
+        }
+        
+        KeycloakAdapterConfigService.INSTANCE.updateConfig(operation, model);
+    }
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceDefinition.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceDefinition.java
new file mode 100644
index 0000000..94dca67
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceDefinition.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.StringListAttributeDefinition;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.ModelType;
+import org.keycloak.subsystem.server.attributes.ModulesListAttributeBuilder;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ThemeResourceDefinition extends SimpleResourceDefinition {
+
+    public static final String TAG_NAME = "theme";
+    
+    // This is the internal name of the singleton resource
+    public static final String RESOURCE_NAME = "defaults";
+    
+    // NOTE: All attributes must be SimpleAttributeDefinition.  If that needs to
+    //       change then refactor starting with lookup() method below.
+    static final SimpleAttributeDefinition STATIC_MAX_AGE =
+        new SimpleAttributeDefinitionBuilder("staticMaxAge", ModelType.LONG, true)
+            .setAllowExpression(true)
+            .setDefaultValue(new ModelNode("2592000"))
+            .setRestartAllServices()
+            .build();
+    
+    static final SimpleAttributeDefinition CACHE_THEMES =
+        new SimpleAttributeDefinitionBuilder("cacheThemes", ModelType.BOOLEAN, true)
+                .setAllowExpression(true)
+                .setDefaultValue(new ModelNode(true))
+                .setAllowNull(false)
+                .setRestartAllServices()
+                .build();
+    
+    static final SimpleAttributeDefinition CACHE_TEMPLATES =
+        new SimpleAttributeDefinitionBuilder("cacheTemplates", ModelType.BOOLEAN, true)
+                .setAllowExpression(true)
+                .setDefaultValue(new ModelNode(true))
+                .setAllowNull(false)
+                .setRestartAllServices()
+                .build();
+    
+    static final SimpleAttributeDefinition WELCOME_THEME =
+        new SimpleAttributeDefinitionBuilder("welcomeTheme", ModelType.STRING, true)
+            .setAllowExpression(true)
+            .setRestartAllServices()
+            .build();
+    
+    static final SimpleAttributeDefinition DEFAULT =
+        new SimpleAttributeDefinitionBuilder("default", ModelType.STRING, true)
+            .setAllowExpression(true)
+            .setRestartAllServices()
+            .build();
+    
+    static final SimpleAttributeDefinition DIR =
+        new SimpleAttributeDefinitionBuilder("dir", ModelType.STRING, true)
+            .setAllowExpression(true)
+            .setDefaultValue(new ModelNode("${jboss.home.dir}/themes"))
+            .setRestartAllServices()
+            .build();
+    
+    static final StringListAttributeDefinition MODULES = new ModulesListAttributeBuilder().build();
+    
+    static final List<AttributeDefinition> ALL_ATTRIBUTES = new ArrayList<>();
+
+    static {
+        ALL_ATTRIBUTES.add(STATIC_MAX_AGE);
+        ALL_ATTRIBUTES.add(CACHE_THEMES);
+        ALL_ATTRIBUTES.add(CACHE_TEMPLATES);
+        ALL_ATTRIBUTES.add(WELCOME_THEME);
+        ALL_ATTRIBUTES.add(DEFAULT);
+        ALL_ATTRIBUTES.add(DIR);
+        ALL_ATTRIBUTES.add(MODULES);
+    }
+
+    private static final Map<String, AttributeDefinition> DEFINITION_LOOKUP = new HashMap<>();
+    static {
+        for (AttributeDefinition def : ALL_ATTRIBUTES) {
+            DEFINITION_LOOKUP.put(def.getXmlName(), def);
+        }
+    }
+    
+    protected static final ReloadRequiredWriteAttributeHandler WRITE_ATTR_HANDLER = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+    
+    protected ThemeResourceDefinition() {
+        super(PathElement.pathElement(TAG_NAME),
+            KeycloakExtension.getResourceDescriptionResolver(TAG_NAME),
+            ThemeResourceAddHandler.INSTANCE,
+            ThemeResourceRemoveHandler.INSTANCE
+        );
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+        
+        for (AttributeDefinition def : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(def, null, WRITE_ATTR_HANDLER);
+        }
+    }
+
+    public static SimpleAttributeDefinition lookup(String name) {
+        return (SimpleAttributeDefinition)DEFINITION_LOOKUP.get(name);
+    }
+    
+}
diff --git a/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceRemoveHandler.java b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceRemoveHandler.java
new file mode 100644
index 0000000..797c564
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/java/org/keycloak/subsystem/server/extension/ThemeResourceRemoveHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.keycloak.subsystem.server.extension;
+
+import org.jboss.as.controller.AbstractRemoveStepHandler;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class ThemeResourceRemoveHandler extends AbstractRemoveStepHandler {
+    
+    public static ThemeResourceRemoveHandler INSTANCE = new ThemeResourceRemoveHandler();
+    
+    private ThemeResourceRemoveHandler() {}
+
+}
diff --git a/wildfly/server-subsystem/src/main/resources/cli/default-keycloak-subsys-config.cli b/wildfly/server-subsystem/src/main/resources/cli/default-keycloak-subsys-config.cli
new file mode 100644
index 0000000..6adef01
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/resources/cli/default-keycloak-subsys-config.cli
@@ -0,0 +1,21 @@
+/subsystem=keycloak-server:add(web-context=auth,master-realm-name=master,scheduled-task-interval=900,providers=[classpath:${jboss.home.dir}/providers/*])
+/subsystem=keycloak-server/theme=defaults/:add(dir=${jboss.home.dir}/themes,staticMaxAge=2592000,cacheTemplates=true,cacheThemes=true)
+/subsystem=keycloak-server/spi=eventsStore/:add(default-provider=jpa)
+/subsystem=keycloak-server/spi=eventsStore/provider=jpa/:add(properties={exclude-events => "[\"REFRESH_TOKEN\"]"},enabled=true)
+/subsystem=keycloak-server/spi=realm/:add(default-provider=jpa)
+/subsystem=keycloak-server/spi=user/:add(default-provider=jpa)
+/subsystem=keycloak-server/spi=userCache/:add
+/subsystem=keycloak-server/spi=userCache/provider=default/:add(enabled=true)
+/subsystem=keycloak-server/spi=userSessionPersister/:add(default-provider=jpa)
+/subsystem=keycloak-server/spi=authorizationPersister/:add(default-provider=jpa)
+/subsystem=keycloak-server/spi=timer/:add(default-provider=basic)
+/subsystem=keycloak-server/spi=connectionsHttpClient/:add
+/subsystem=keycloak-server/spi=connectionsHttpClient/provider=default/:add(enabled=true)
+/subsystem=keycloak-server/spi=connectionsJpa/:add
+/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:add(properties={dataSource => "java:jboss/datasources/KeycloakDS",initializeEmpty => "true",migrationStrategy => "update",migrationExport => "${jboss.home.dir}/keycloak-database-update.sql"},enabled=true)
+/subsystem=keycloak-server/spi=realmCache/:add
+/subsystem=keycloak-server/spi=realmCache/provider=default/:add(enabled=true)
+/subsystem=keycloak-server/spi=connectionsInfinispan/:add(default-provider=default)
+/subsystem=keycloak-server/spi=connectionsInfinispan/provider=default/:add(properties={cacheContainer => "java:comp/env/infinispan/Keycloak"},enabled=true)
+/subsystem=keycloak-server/spi=jta-lookup/:add(default-provider=${keycloak.jta.lookup.provider:jboss})
+/subsystem=keycloak-server/spi=jta-lookup/provider=jboss/:add(enabled=true)
\ No newline at end of file
diff --git a/wildfly/server-subsystem/src/main/resources/default-config/keycloak-server-default-config.xml b/wildfly/server-subsystem/src/main/resources/default-config/keycloak-server-default-config.xml
new file mode 100644
index 0000000..e520611
--- /dev/null
+++ b/wildfly/server-subsystem/src/main/resources/default-config/keycloak-server-default-config.xml
@@ -0,0 +1 @@
+${keycloak.server.subsys.default.config}
\ No newline at end of file
diff --git a/wildfly/server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties b/wildfly/server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties
index bf29d06..8d5c5a7 100755
--- a/wildfly/server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties
+++ b/wildfly/server-subsystem/src/main/resources/org/keycloak/subsystem/server/extension/LocalDescriptions.properties
@@ -15,7 +15,38 @@
 # limitations under the License.
 #
 
+keycloak-server.migrate-json=Migrate keycloak-server.json to standalone.xml or domain.xml
+keycloak-server.migrate-json.file=Optional local path to keycloak-server.json
+
 keycloak-server.subsystem=Keycloak subsystem
 keycloak-server.subsystem.add=Operation Adds Keycloak subsystem
 keycloak-server.subsystem.remove=Operation removes Keycloak subsystem
 keycloak-server.subsystem.web-context=Web context where Keycloak server is bound. Default value is 'auth'.
+keycloak-server.subsystem.providers=Paths to search for Keycloak provider jars.
+keycloak-server.subsystem.master-realm-name=The name of the master admin realm.
+keycloak-server.subsystem.scheduled-task-interval=The interval (in seconds) to run scheduled tasks.
+keycloak-server.subsystem.spi=A Service Provider type.
+keycloak-server.subsystem.theme=Theme configuration properties.
+
+keycloak-server.theme=Theme configuration properties.
+keycloak-server.theme.add=Add the theme config properties.
+keycloak-server.theme.remove=Remove the theme config properties.
+keycloak-server.theme.staticMaxAge=Maximum time the browser should cache theme resources. A value of -1 will disable caching.
+keycloak-server.theme.cacheThemes=If true, themes are cached.
+keycloak-server.theme.cacheTemplates=If true, theme templates are cached.
+keycloak-server.theme.welcomeTheme=The welcome theme.
+keycloak-server.theme.default=The default theme to use if no theme is specified for a realm.
+keycloak-server.theme.dir=Directory where themes can be located.
+keycloak-server.theme.modules=List of modules containing themes.
+
+keycloak-server.spi=A Service Provider type.
+keycloak-server.spi.add=Add an spi.
+keycloak-server.spi.remove=Remove an spi.
+keycloak-server.spi.default-provider=The default provider for the spi.
+keycloak-server.spi.provider=A provider for the spi.
+
+keycloak-server.provider=A provider for the spi.
+keycloak-server.provider.add=Add a provider.
+keycloak-server.provider.remove=Remove a provider.
+keycloak-server.provider.enabled=Enable or disable the provider.
+keycloak-server.provider.properties=The properties for the provider.
diff --git a/wildfly/server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd b/wildfly/server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd
index df02124..fa9f9e0 100755
--- a/wildfly/server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd
+++ b/wildfly/server-subsystem/src/main/resources/schema/wildfly-keycloak-server_1_1.xsd
@@ -1,21 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
-  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
-  ~ and other contributors as indicated by the @author tags.
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
 
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
            targetNamespace="urn:jboss:domain:keycloak-server:1.1"
@@ -35,8 +35,73 @@
                 ]]>
             </xs:documentation>
         </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="1">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
             <xs:element name="web-context" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="providers" type="providersLocationType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="master-realm-name" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="scheduled-task-interval" type="xs:long" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="theme" type="themeDefaultsType" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="spi" type="spiType" minOccurs="0" maxOccurs="unbounded"/>
         </xs:choice>
+        
+    </xs:complexType>
+    
+    <xs:complexType name="providersLocationType">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="provider" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:choice>
+    </xs:complexType>
+    
+    <xs:complexType name="themeDefaultsType">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="staticMaxAge" type="xs:long" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="cacheThemes" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="cacheTemplates" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="welcomeTheme" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="default" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="dir" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="modules" type="modulesType" minOccurs="0" maxOccurs="1"/>
+        </xs:choice>
+    </xs:complexType>
+    
+    <xs:complexType name="modulesType">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="module" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:choice>
+    </xs:complexType>
+    
+    <xs:complexType name="spiType">
+        <xs:sequence>
+            <xs:element name="default-provider" type="xs:string" minOccurs="0" maxOccurs="1"/>
+            <xs:element name="provider" type="providerType" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" use="required"/>
+    </xs:complexType>
+    
+    <xs:complexType name="providerType">
+        <xs:sequence>
+            <xs:element name="properties" type="properties" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+        <xs:attribute name="name" use="required"/>
+        <xs:attribute name="enabled" use="required"/>
+    </xs:complexType>
+    
+    <xs:complexType name="properties">
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="property" type="propertyType" maxOccurs="unbounded"/>
+            <xs:element name="list" type="listType" maxOccurs="unbounded"/>
+        </xs:choice>
+    </xs:complexType>
+
+    <xs:complexType name="propertyType">
+        <xs:attribute name="name" use="required"/>
+        <xs:attribute name="value" use="optional"/>
+    </xs:complexType>
+    
+    <xs:complexType name="listType">
+        <xs:sequence>
+            <xs:element name="value" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" use="required"/>
     </xs:complexType>
 </xs:schema>
diff --git a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml
index c269c31..67bf03e 100644
--- a/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml
+++ b/wildfly/server-subsystem/src/main/resources/subsystem-templates/keycloak-server.xml
@@ -1,25 +1,23 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <!--
-  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
-  ~ and other contributors as indicated by the @author tags.
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
+~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+~ and other contributors as indicated by the @author tags.
+~
+~ Licensed under the Apache License, Version 2.0 (the "License");
+~ you may not use this file except in compliance with the License.
+~ You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+-->
 
 <!--  Template used by WildFly build when directed to include Keycloak subsystem in a configuration. -->
 <config>
-   <extension-module>org.keycloak.keycloak-server-subsystem</extension-module>
-   <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
-      <web-context>auth</web-context>
-   </subsystem>
+    <extension-module>org.keycloak.keycloak-server-subsystem</extension-module>
+    ${keycloak.server.subsys.default.config}
 </config>
diff --git a/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/JsonConfigConverterTestCase.java b/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/JsonConfigConverterTestCase.java
new file mode 100644
index 0000000..4c6bf04
--- /dev/null
+++ b/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/JsonConfigConverterTestCase.java
@@ -0,0 +1,446 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.subsystem.server.extension;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.PathElement;
+import org.jboss.dmr.ModelNode;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
+
+/**
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
+ */
+public class JsonConfigConverterTestCase {
+
+    private final PathElement domainRoot = PathElement.pathElement("profile", "auth-server-clustered");
+    private final PathAddress domainAddress = PathAddress.pathAddress(domainRoot)
+                                                         .append(KeycloakExtension.PATH_SUBSYSTEM);
+    private final PathAddress standaloneAddress = PathAddress.pathAddress(KeycloakExtension.PATH_SUBSYSTEM);
+
+    @Test
+    public void testConvertJsonStandaloneWithModules() throws Exception {
+        String json = basicJsonConfig(true);
+        List<ModelNode> expResult = expectedOperations(true, false);
+        
+        List<ModelNode> result = JsonConfigConverter.convertJsonConfig(json, standaloneAddress);
+        assertEquals(expResult, result);
+    }
+    
+    @Test
+    public void testConvertJsonStandaloneWithoutModules() throws Exception {
+        String json = basicJsonConfig(false);
+        List<ModelNode> expResult = expectedOperations(false, false);
+        
+        List<ModelNode> result = JsonConfigConverter.convertJsonConfig(json, standaloneAddress);
+        assertEquals(expResult, result);
+    }
+    
+    @Test
+    public void testConvertJsonDomainWithModules() throws Exception {
+        String json = basicJsonConfig(true);
+        List<ModelNode> expResult = expectedOperations(true, true);
+        
+        List<ModelNode> result = JsonConfigConverter.convertJsonConfig(json, domainAddress);
+        assertEquals(expResult, result);
+    }
+    
+    @Test
+    public void testConvertJsonDomainWithoutModules() throws Exception {
+        String json = basicJsonConfig(false);
+        List<ModelNode> expResult = expectedOperations(false, true);
+        
+        List<ModelNode> result = JsonConfigConverter.convertJsonConfig(json, domainAddress);
+        assertEquals(expResult, result);
+    }
+    
+    private String basicJsonConfig(boolean includeModules) {
+        String basicConfig = 
+              "{\n"
+            + "    \"providers\": [\n"
+            + "        \"classpath:${jboss.home.dir}/providers/*\"\n"
+            + "    ],\n"
+            + "\n"
+            + "    \"admin\": {\n"
+            + "        \"realm\": \"master\"\n"
+            + "    },\n"
+            + "\n"
+            + "    \"eventsStore\": {\n"
+            + "        \"provider\": \"jpa\",\n"
+            + "        \"jpa\": {\n"
+            + "            \"exclude-events\": [ \"REFRESH_TOKEN\" ]\n"
+            + "        }\n"
+            + "    },\n"
+            + "\n"
+            + "    \"realm\": {\n"
+            + "        \"provider\": \"jpa\"\n"
+            + "    },\n"
+            + "\n"
+            + "    \"user\": {\n"
+            + "        \"provider\": \"jpa\"\n"
+            + "    },\n"
+            + "\n"
+            + "    \"userCache\": {\n"
+            + "        \"default\" : {\n"
+            + "            \"enabled\": true\n"
+            + "        }\n"
+            + "    },\n"
+            + "\n"
+            + "    \"userSessionPersister\": {\n"
+            + "        \"provider\": \"jpa\"\n"
+            + "    },\n"
+            + "\n"
+            + "    \"authorizationPersister\": {\n"
+            + "        \"provider\": \"jpa\"\n"
+            + "    },\n"
+            + "\n"
+            + "    \"timer\": {\n"
+            + "        \"provider\": \"basic\"\n"
+            + "    },\n"
+            + "\n"
+            + "    \"theme\": {\n"
+            + "        \"staticMaxAge\": 2592001,\n"
+            + "        \"cacheTemplates\": false,\n"
+            + "        \"cacheThemes\": false,\n"
+            + "        \"welcomeTheme\": \"welcome\",\n"
+            + "        \"default\": \"default\",\n"
+            + "        \"folder\": {\n"
+            + "          \"dir\": \"${jboss.home.dir}/themes\"\n";
+            
+        
+        if (includeModules) {
+            basicConfig +=
+              "        },\n"
+            + "        \"module\": {\n"
+            + "          \"modules\": [ \"org.keycloak.example.themes\" ]\n"
+            + "         }\n";
+        } else {
+            basicConfig +=
+              "        }\n";
+        }
+        
+        basicConfig +=
+              "     },\n"
+            + "\n"
+            + "    \"scheduled\": {\n"
+            + "        \"interval\": 900\n"
+            + "    },\n"
+            + "\n"
+            + "    \"connectionsHttpClient\": {\n"
+            + "        \"default\": {}\n"
+            + "    },\n"
+            + "\n"
+            + "    \"connectionsJpa\": {\n"
+            + "        \"default\": {\n"
+            + "            \"dataSource\": \"java:jboss/datasources/KeycloakDS\",\n"
+            + "            \"databaseSchema\": \"update\"\n"
+            + "        }\n"
+            + "    },\n"
+            + "\n"
+            + "    \"realmCache\": {\n"
+            + "        \"default\" : {\n"
+            + "            \"enabled\": true\n"
+            + "        }\n"
+            + "    },\n"
+            + "\n"
+            + "    \"connectionsInfinispan\": {\n"
+            + "        \"provider\": \"default\",\n"
+            + "        \"default\": {\n"
+            + "            \"cacheContainer\" : \"java:comp/env/infinispan/Keycloak\"\n"
+            + "        }\n"
+            + "    }\n"
+            + "}";
+        
+        return basicConfig;
+    }
+    
+    private List<ModelNode> expectedOperations(boolean includeModules, boolean isDomain) {
+        List<ModelNode> ops = new ArrayList<>();
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"write-attribute\",\n" +
+            "    \"address\" => [(\"subsystem\" => \"keycloak-server\")],\n" +
+            "    \"name\" => \"master-realm-name\",\n" +
+            "    \"value\" => \"master\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"write-attribute\",\n" +
+            "    \"address\" => [(\"subsystem\" => \"keycloak-server\")],\n" +
+            "    \"name\" => \"scheduled-task-interval\",\n" +
+            "    \"value\" => 900L\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"write-attribute\",\n" +
+            "    \"address\" => [(\"subsystem\" => \"keycloak-server\")],\n" +
+            "    \"name\" => \"providers\",\n" +
+            "    \"value\" => [\"classpath:${jboss.home.dir}/providers/*\"]\n" +
+            "}"
+        ));
+        
+        if (includeModules) {
+            ops.add(ModelNode.fromString(
+                "{\n" +
+                "    \"operation\" => \"add\",\n" +
+                "    \"address\" => [\n" +
+                "        (\"subsystem\" => \"keycloak-server\"),\n" +
+                "        (\"theme\" => \"defaults\")\n" +
+                "    ],\n" +
+                "    \"staticMaxAge\" => 2592001L,\n" +
+                "    \"cacheTemplates\" => false,\n" +
+                "    \"cacheThemes\" => false,\n" +
+                "    \"dir\" => \"${jboss.home.dir}/themes\",\n" +
+                "    \"welcomeTheme\" => \"welcome\",\n" +
+                "    \"default\" => \"default\",\n" +
+                "    \"modules\" => [\"org.keycloak.example.themes\"]\n" +
+                "}"
+            ));
+        } else {
+            ops.add(ModelNode.fromString(
+                "{\n" +
+                "    \"operation\" => \"add\",\n" +
+                "    \"address\" => [\n" +
+                "        (\"subsystem\" => \"keycloak-server\"),\n" +
+                "        (\"theme\" => \"defaults\")\n" +
+                "    ],\n" +
+                "    \"staticMaxAge\" => 2592001L,\n" +
+                "    \"cacheTemplates\" => false,\n" +
+                "    \"cacheThemes\" => false,\n" +
+                "    \"dir\" => \"${jboss.home.dir}/themes\",\n" +
+                "    \"welcomeTheme\" => \"welcome\",\n" +
+                "    \"default\" => \"default\",\n" +
+                "}"
+            ));
+        }
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"eventsStore\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"jpa\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"eventsStore\"),\n" +
+            "        (\"provider\" => \"jpa\")\n" +
+            "    ],\n" +
+            "    \"properties\" => {\"exclude-events\" => \"[\\\"REFRESH_TOKEN\\\"]\"},\n" +
+            "    \"enabled\" => true\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"realm\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"jpa\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"user\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"jpa\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"userCache\")\n" +
+            "    ]\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"userCache\"),\n" +
+            "        (\"provider\" => \"default\")\n" +
+            "    ],\n" +
+            "    \"enabled\" => true\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"userSessionPersister\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"jpa\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"authorizationPersister\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"jpa\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"timer\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"basic\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"connectionsHttpClient\")\n" +
+            "    ]\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"connectionsHttpClient\"),\n" +
+            "        (\"provider\" => \"default\")\n" +
+            "    ],\n" +
+            "    \"enabled\" => true\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"connectionsJpa\")\n" +
+            "    ]\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"connectionsJpa\"),\n" +
+            "        (\"provider\" => \"default\")\n" +
+            "    ],\n" +
+            "    \"properties\" => {\n" +
+            "        \"dataSource\" => \"java:jboss/datasources/KeycloakDS\",\n" +
+            "        \"databaseSchema\" => \"update\"\n" +
+            "    },\n" +
+            "    \"enabled\" => true\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"realmCache\")\n" +
+            "    ]\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"realmCache\"),\n" +
+            "        (\"provider\" => \"default\")\n" +
+            "    ],\n" +
+            "    \"enabled\" => true\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"connectionsInfinispan\")\n" +
+            "    ],\n" +
+            "    \"default-provider\" => \"default\"\n" +
+            "}"
+        ));
+        
+        ops.add(ModelNode.fromString(
+            "{\n" +
+            "    \"operation\" => \"add\",\n" +
+            "    \"address\" => [\n" +
+            "        (\"subsystem\" => \"keycloak-server\"),\n" +
+            "        (\"spi\" => \"connectionsInfinispan\"),\n" +
+            "        (\"provider\" => \"default\")\n" +
+            "    ],\n" +
+            "    \"properties\" => {\"cacheContainer\" => \"java:comp/env/infinispan/Keycloak\"},\n" +
+            "    \"enabled\" => true\n" +
+            "}"
+        ));
+
+        if (isDomain) { // prepend the domain root
+            for (ModelNode op : ops) {
+                PathAddress addr = PathAddress.pathAddress(op.get(ADDRESS));
+                PathAddress domainAddr = PathAddress.pathAddress(domainRoot).append(addr);
+                op.get(ADDRESS).set(domainAddr.toModelNode());
+            }
+        }
+        
+        return ops;
+    }
+}
\ No newline at end of file
diff --git a/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java b/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java
index c84acc2..0bc4110 100755
--- a/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java
+++ b/wildfly/server-subsystem/src/test/java/org/keycloak/subsystem/server/extension/SubsystemParsingTestCase.java
@@ -17,10 +17,9 @@
 package org.keycloak.subsystem.server.extension;
 
 import java.io.IOException;
+import java.util.Properties;
 
 import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;
-import org.jboss.dmr.ModelNode;
-import org.junit.Test;
 
 /**
  * Tests all management expects for subsystem, parsing, marshaling, model definition and other
@@ -38,14 +37,14 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
         super(KeycloakExtension.SUBSYSTEM_NAME, new KeycloakExtension());
     }
 
-    @Test
-    public void testJson() throws Exception {
-        ModelNode node = new ModelNode();
-        node.get("web-context").set("auth");
-
-        System.out.println("json=" + node.toJSONString(false));
+    @Override
+    protected Properties getResolvedProperties() {
+        Properties properties = new Properties();
+        properties.put("jboss.home.dir", System.getProperty("java.io.tmpdir"));
+        properties.put("keycloak.jta.lookup.provider", "jboss");
+        return properties;
     }
-
+    
     @Override
     protected String getSubsystemXml() throws IOException {
         return readResource("keycloak-server-1.1.xml");
diff --git a/wildfly/server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml b/wildfly/server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml
index 103e162..e520611 100644
--- a/wildfly/server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml
+++ b/wildfly/server-subsystem/src/test/resources/org/keycloak/subsystem/server/extension/keycloak-server-1.1.xml
@@ -1,20 +1 @@
-<!--
-  ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
-  ~ and other contributors as indicated by the @author tags.
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~ http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
-    <web-context>auth</web-context>
-</subsystem>
\ No newline at end of file
+${keycloak.server.subsys.default.config}
\ No newline at end of file