keycloak-uncached

Changes

Details

diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
index 1d978dd..e95f6aa 100755
--- a/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/assembly.xml
@@ -29,6 +29,11 @@
             <destName>standalone-keycloak.xml</destName>
         </file>
         <file>
+            <source>${project.build.directory}/standalone-ha.xml</source>
+            <outputDirectory>standalone/configuration</outputDirectory>
+            <destName>standalone-keycloak-ha.xml</destName>
+        </file>
+        <file>
             <source>src/main/keycloak-server.json</source>
             <outputDirectory>standalone/configuration</outputDirectory>
         </file>
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/pom.xml b/distribution/server-overlay/eap6/eap6-server-overlay/pom.xml
index 4b5acc7..9f9fb74 100755
--- a/distribution/server-overlay/eap6/eap6-server-overlay/pom.xml
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/pom.xml
@@ -72,6 +72,25 @@
                             </transformationSets>
                         </configuration>
                     </execution>
+                    <execution>
+                        <id>generate-resources-2</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>transform</goal>
+                        </goals>
+                        <configuration>
+                            <transformationSets>
+                                <transformationSet>
+                                    <dir>src/main</dir>
+                                    <stylesheet>src/main/xslt/standalone-ha.xsl</stylesheet>
+                                    <includes>
+                                        <include>standalone-ha.xml</include>
+                                    </includes>
+                                    <outputDir>${project.build.directory}</outputDir>
+                                </transformationSet>
+                            </transformationSets>
+                        </configuration>
+                    </execution>
                 </executions>
             </plugin>
             <plugin>
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/src/main/standalone-ha.xml b/distribution/server-overlay/eap6/eap6-server-overlay/src/main/standalone-ha.xml
new file mode 100644
index 0000000..e208a7d
--- /dev/null
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/src/main/standalone-ha.xml
@@ -0,0 +1,421 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<server xmlns="urn:jboss:domain:1.7">
+    <extensions>
+        <extension module="org.jboss.as.clustering.infinispan"/>
+        <extension module="org.jboss.as.clustering.jgroups"/>
+        <extension module="org.jboss.as.connector"/>
+        <extension module="org.jboss.as.deployment-scanner"/>
+        <extension module="org.jboss.as.ee"/>
+        <extension module="org.jboss.as.ejb3"/>
+        <extension module="org.jboss.as.jaxrs"/>
+        <extension module="org.jboss.as.jdr"/>
+        <extension module="org.jboss.as.jmx"/>
+        <extension module="org.jboss.as.jpa"/>
+        <extension module="org.jboss.as.jsf"/>
+        <extension module="org.jboss.as.logging"/>
+        <extension module="org.jboss.as.mail"/>
+        <extension module="org.jboss.as.modcluster"/>
+        <extension module="org.jboss.as.naming"/>
+        <extension module="org.jboss.as.pojo"/>
+        <extension module="org.jboss.as.remoting"/>
+        <extension module="org.jboss.as.sar"/>
+        <extension module="org.jboss.as.security"/>
+        <extension module="org.jboss.as.threads"/>
+        <extension module="org.jboss.as.transactions"/>
+        <extension module="org.jboss.as.web"/>
+        <extension module="org.jboss.as.webservices"/>
+        <extension module="org.jboss.as.weld"/>
+    </extensions>
+    <management>
+        <security-realms>
+            <security-realm name="ManagementRealm">
+                <authentication>
+                    <local default-user="$local" skip-group-loading="true"/>
+                    <properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization map-groups-to-roles="false">
+                    <properties path="mgmt-groups.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+            <security-realm name="ApplicationRealm">
+                <authentication>
+                    <local default-user="$local" allowed-users="*" skip-group-loading="true"/>
+                    <properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
+                </authentication>
+                <authorization>
+                    <properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
+                </authorization>
+            </security-realm>
+        </security-realms>
+        <audit-log>
+            <formatters>
+                <json-formatter name="json-formatter"/>
+            </formatters>
+            <handlers>
+                <file-handler name="file" formatter="json-formatter" relative-to="jboss.server.data.dir" path="audit-log.log"/>
+            </handlers>
+            <logger log-boot="true" log-read-only="false" enabled="false">
+                <handlers>
+                    <handler name="file"/>
+                </handlers>
+            </logger>
+        </audit-log>
+        <management-interfaces>
+            <native-interface security-realm="ManagementRealm">
+                <socket-binding native="management-native"/>
+            </native-interface>
+            <http-interface security-realm="ManagementRealm">
+                <socket-binding http="management-http"/>
+            </http-interface>
+        </management-interfaces>
+        <access-control provider="simple">
+            <role-mapping>
+                <role name="SuperUser">
+                    <include>
+                        <user name="$local"/>
+                    </include>
+                </role>
+            </role-mapping>
+        </access-control>
+    </management>
+    <profile>
+        <subsystem xmlns="urn:jboss:domain:logging:1.5">
+            <console-handler name="CONSOLE">
+                <level name="INFO"/>
+                <formatter>
+                    <named-formatter name="COLOR-PATTERN"/>
+                </formatter>
+            </console-handler>
+            <periodic-rotating-file-handler name="FILE" autoflush="true">
+                <formatter>
+                    <named-formatter name="PATTERN"/>
+                </formatter>
+                <file relative-to="jboss.server.log.dir" path="server.log"/>
+                <suffix value=".yyyy-MM-dd"/>
+                <append value="true"/>
+            </periodic-rotating-file-handler>
+            <logger category="com.arjuna">
+                <level name="WARN"/>
+            </logger>
+            <logger category="org.apache.tomcat.util.modeler">
+                <level name="WARN"/>
+            </logger>
+            <logger category="org.jboss.as.config">
+                <level name="DEBUG"/>
+            </logger>
+            <logger category="sun.rmi">
+                <level name="WARN"/>
+            </logger>
+            <logger category="jacorb">
+                <level name="WARN"/>
+            </logger>
+            <logger category="jacorb.config">
+                <level name="ERROR"/>
+            </logger>
+            <root-logger>
+                <level name="INFO"/>
+                <handlers>
+                    <handler name="CONSOLE"/>
+                    <handler name="FILE"/>
+                </handlers>
+            </root-logger>
+            <formatter name="PATTERN">
+                <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
+            </formatter>
+            <formatter name="COLOR-PATTERN">
+                <pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
+            </formatter>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:datasources:1.2">
+            <datasources>
+                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
+                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
+                    <driver>h2</driver>
+                    <security>
+                        <user-name>sa</user-name>
+                        <password>sa</password>
+                    </security>
+                </datasource>
+                <drivers>
+                    <driver name="h2" module="com.h2database.h2">
+                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
+                    </driver>
+                </drivers>
+            </datasources>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:deployment-scanner:1.1">
+            <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ee:1.2">
+            <spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
+            <jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
+            <annotation-property-replacement>false</annotation-property-replacement>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:ejb3:1.5">
+            <session-bean>
+                <stateless>
+                    <bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
+                </stateless>
+                <stateful default-access-timeout="5000" cache-ref="simple" clustered-cache-ref="clustered"/>
+                <singleton default-access-timeout="5000"/>
+            </session-bean>
+            <pools>
+                <bean-instance-pools>
+                    <strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                    <strict-max-pool name="mdb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
+                </bean-instance-pools>
+            </pools>
+            <caches>
+                <cache name="simple" aliases="NoPassivationCache"/>
+                <cache name="passivating" passivation-store-ref="file" aliases="SimpleStatefulCache"/>
+                <cache name="clustered" passivation-store-ref="infinispan" aliases="StatefulTreeCache"/>
+            </caches>
+            <passivation-stores>
+                <file-passivation-store name="file"/>
+                <cluster-passivation-store name="infinispan" cache-container="ejb"/>
+            </passivation-stores>
+            <async thread-pool-name="default"/>
+            <timer-service thread-pool-name="default" default-data-store="default-file-store">
+                <data-stores>
+                    <file-data-store name="default-file-store" path="timer-service-data" relative-to="jboss.server.data.dir"/>
+                </data-stores>
+            </timer-service>
+            <remote connector-ref="remoting-connector" thread-pool-name="default"/>
+            <thread-pools>
+                <thread-pool name="default">
+                    <max-threads count="10"/>
+                    <keepalive-time time="100" unit="milliseconds"/>
+                </thread-pool>
+            </thread-pools>
+            <default-security-domain value="other"/>
+            <default-missing-method-permissions-deny-access value="true"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:infinispan:1.5">
+            <cache-container name="singleton" aliases="cluster ha-partition" default-cache="default">
+                <transport lock-timeout="60000"/>
+                <replicated-cache name="default" mode="SYNC" batching="true">
+                    <locking isolation="REPEATABLE_READ"/>
+                </replicated-cache>
+            </cache-container>
+            <cache-container name="web" aliases="standard-session-cache" default-cache="repl" module="org.jboss.as.clustering.web.infinispan">
+                <transport lock-timeout="60000"/>
+                <replicated-cache name="repl" mode="ASYNC" batching="true">
+                    <file-store/>
+                </replicated-cache>
+                <replicated-cache name="sso" mode="SYNC" batching="true"/>
+                <distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
+                    <file-store/>
+                </distributed-cache>
+            </cache-container>
+            <cache-container name="ejb" aliases="sfsb sfsb-cache" default-cache="repl" module="org.jboss.as.clustering.ejb3.infinispan">
+                <transport lock-timeout="60000"/>
+                <replicated-cache name="repl" mode="ASYNC" batching="true">
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <file-store/>
+                </replicated-cache>
+                <!--
+                  ~  Clustered cache used internally by EJB subsytem for managing the client-mapping(s) of
+                  ~                 the socketbinding referenced by the EJB remoting connector 
+                  -->
+                <replicated-cache name="remote-connector-client-mappings" mode="SYNC" batching="true"/>
+                <distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <file-store/>
+                </distributed-cache>
+            </cache-container>
+            <cache-container name="hibernate" default-cache="local-query" module="org.jboss.as.jpa.hibernate:4">
+                <transport lock-timeout="60000"/>
+                <local-cache name="local-query">
+                    <transaction mode="NONE"/>
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </local-cache>
+                <invalidation-cache name="entity" mode="SYNC">
+                    <transaction mode="NON_XA"/>
+                    <eviction strategy="LRU" max-entries="10000"/>
+                    <expiration max-idle="100000"/>
+                </invalidation-cache>
+                <replicated-cache name="timestamps" mode="ASYNC">
+                    <transaction mode="NONE"/>
+                    <eviction strategy="NONE"/>
+                </replicated-cache>
+            </cache-container>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jaxrs:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jca:1.1">
+            <archive-validation enabled="true" fail-on-error="true" fail-on-warn="false"/>
+            <bean-validation enabled="true"/>
+            <default-workmanager>
+                <short-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </short-running-threads>
+                <long-running-threads>
+                    <core-threads count="50"/>
+                    <queue-length count="50"/>
+                    <max-threads count="50"/>
+                    <keepalive-time time="10" unit="seconds"/>
+                </long-running-threads>
+            </default-workmanager>
+            <cached-connection-manager/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jdr:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:jgroups:1.1" default-stack="udp">
+            <stack name="udp">
+                <transport type="UDP" socket-binding="jgroups-udp"/>
+                <protocol type="PING"/>
+                <protocol type="MERGE3"/>
+                <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
+                <protocol type="FD"/>
+                <protocol type="VERIFY_SUSPECT"/>
+                <protocol type="pbcast.NAKACK"/>
+                <protocol type="UNICAST2"/>
+                <protocol type="pbcast.STABLE"/>
+                <protocol type="pbcast.GMS"/>
+                <protocol type="UFC"/>
+                <protocol type="MFC"/>
+                <protocol type="FRAG2"/>
+                <protocol type="RSVP"/>
+            </stack>
+            <stack name="tcp">
+                <transport type="TCP" socket-binding="jgroups-tcp"/>
+                <protocol type="MPING" socket-binding="jgroups-mping"/>
+                <protocol type="MERGE2"/>
+                <protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
+                <protocol type="FD"/>
+                <protocol type="VERIFY_SUSPECT"/>
+                <protocol type="pbcast.NAKACK"/>
+                <protocol type="UNICAST2"/>
+                <protocol type="pbcast.STABLE"/>
+                <protocol type="pbcast.GMS"/>
+                <protocol type="UFC"/>
+                <protocol type="MFC"/>
+                <protocol type="FRAG2"/>
+                <protocol type="RSVP"/>
+            </stack>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jmx:1.3">
+            <expose-resolved-model/>
+            <expose-expression-model/>
+            <remoting-connector/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jpa:1.1">
+            <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:jsf:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:mail:1.2">
+            <mail-session name="default" jndi-name="java:jboss/mail/Default">
+                <smtp-server outbound-socket-binding-ref="mail-smtp"/>
+            </mail-session>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:modcluster:1.2">
+            <mod-cluster-config advertise-socket="modcluster" connector="ajp">
+                <dynamic-load-provider>
+                    <load-metric type="busyness"/>
+                </dynamic-load-provider>
+            </mod-cluster-config>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:naming:1.4">
+            <remote-naming/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:pojo:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:remoting:1.2">
+            <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:resource-adapters:1.1"/>
+        <subsystem xmlns="urn:jboss:domain:sar:1.0"/>
+        <subsystem xmlns="urn:jboss:domain:security:1.2">
+            <security-domains>
+                <security-domain name="other" cache-type="default">
+                    <authentication>
+                        <login-module code="Remoting" flag="optional">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                        <login-module code="RealmDirect" flag="required">
+                            <module-option name="password-stacking" value="useFirstPass"/>
+                        </login-module>
+                    </authentication>
+                </security-domain>
+                <security-domain name="jboss-web-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+                <security-domain name="jboss-ejb-policy" cache-type="default">
+                    <authorization>
+                        <policy-module code="Delegating" flag="required"/>
+                    </authorization>
+                </security-domain>
+            </security-domains>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:threads:1.1"/>
+        <subsystem xmlns="urn:jboss:domain:transactions:1.5">
+            <core-environment>
+                <process-id>
+                    <uuid/>
+                </process-id>
+            </core-environment>
+            <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/>
+            <coordinator-environment default-timeout="300"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:web:2.2" default-virtual-server="default-host" native="false">
+            <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
+            <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
+            <virtual-server name="default-host" enable-welcome-root="true">
+                <alias name="localhost"/>
+                <alias name="example.com"/>
+            </virtual-server>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:webservices:1.2">
+            <modify-wsdl-address>true</modify-wsdl-address>
+            <wsdl-host>${jboss.bind.address:127.0.0.1}</wsdl-host>
+            <endpoint-config name="Standard-Endpoint-Config"/>
+            <endpoint-config name="Recording-Endpoint-Config">
+                <pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
+                    <handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
+                </pre-handler-chain>
+            </endpoint-config>
+            <client-config name="Standard-Client-Config"/>
+        </subsystem>
+        <subsystem xmlns="urn:jboss:domain:weld:1.0"/>
+    </profile>
+    <interfaces>
+        <interface name="management">
+            <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
+        </interface>
+        <interface name="public">
+            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
+        </interface>
+        <!-- TODO - only show this if the jacorb subsystem is added  -->
+        <interface name="unsecure">
+            <!--
+              ~  Used for IIOP sockets in the standard configuration.
+              ~                  To secure JacORB you need to setup SSL 
+              -->
+            <inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
+        </interface>
+    </interfaces>
+    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
+        <socket-binding name="management-native" interface="management" port="${jboss.management.native.port:9999}"/>
+        <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
+        <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9443}"/>
+        <socket-binding name="ajp" port="8009"/>
+        <socket-binding name="http" port="8080"/>
+        <socket-binding name="https" port="8443"/>
+        <socket-binding name="jgroups-mping" port="0" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45700"/>
+        <socket-binding name="jgroups-tcp" port="7600"/>
+        <socket-binding name="jgroups-tcp-fd" port="57600"/>
+        <socket-binding name="jgroups-udp" port="55200" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45688"/>
+        <socket-binding name="jgroups-udp-fd" port="54200"/>
+        <socket-binding name="modcluster" port="0" multicast-address="224.0.1.105" multicast-port="23364"/>
+        <socket-binding name="remoting" port="4447"/>
+        <socket-binding name="txn-recovery-environment" port="4712"/>
+        <socket-binding name="txn-status-manager" port="4713"/>
+        <outbound-socket-binding name="mail-smtp">
+            <remote-destination host="localhost" port="25"/>
+        </outbound-socket-binding>
+    </socket-binding-group>
+</server>
\ No newline at end of file
diff --git a/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone-ha.xsl b/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone-ha.xsl
new file mode 100755
index 0000000..31f681f
--- /dev/null
+++ b/distribution/server-overlay/eap6/eap6-server-overlay/src/main/xslt/standalone-ha.xsl
@@ -0,0 +1,76 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xalan="http://xml.apache.org/xalan"
+                xmlns:j="urn:jboss:domain:1.7"
+                xmlns:ds="urn:jboss:domain:datasources:1.2"
+                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">
+
+    <xsl:param name="config"/>
+    <xsl:variable name="log" select="'urn:jboss:domain:logging:'"/>
+    <xsl:variable name="inf" select="'urn:jboss:domain:infinispan:'"/>
+
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
+    <xsl:strip-space elements="*"/>
+
+    <xsl:template match="//j:extensions">
+        <xsl:copy>
+            <xsl:apply-templates select="node()|@*"/>
+            <extension module="org.keycloak.keycloak-server-subsystem"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//ds:datasources">
+        <xsl:copy>
+            <xsl:apply-templates select="node()[name(.)='datasource']"/>
+            <datasource jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
+                <connection-url>jdbc:h2:${jboss.server.data.dir}/keycloak;AUTO_SERVER=TRUE</connection-url>
+                <driver>h2</driver>
+                <security>
+                    <user-name>sa</user-name>
+                    <password>sa</password>
+                </security>
+            </datasource>
+            <xsl:apply-templates select="node()[name(.)='drivers']"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $inf)]">
+        <xsl:copy>
+            <cache-container name="keycloak" jndi-name="infinispan/Keycloak" start="EAGER">
+                <transport lock-timeout="60000"/>
+                <invalidation-cache name="realms" mode="SYNC"/>
+                <invalidation-cache name="users" mode="SYNC"/>
+                <distributed-cache name="sessions" mode="SYNC" owners="1"/>
+                <distributed-cache name="loginFailures" mode="SYNC" owners="1"/>
+            </cache-container>
+            <xsl:apply-templates select="node()|@*"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <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>
+    </xsl:template>
+
+    <xsl:template match="//*[local-name()='subsystem' and starts-with(namespace-uri(), $log)]">
+        <xsl:copy>
+            <xsl:apply-templates select="node()|@*"/>
+            <logger category="org.jboss.resteasy.resteasy_jaxrs.i18n">
+                <level name="ERROR"/>
+            </logger>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()" />
+        </xsl:copy>
+    </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/distribution/server-overlay/wf9-server-overlay/assembly.xml b/distribution/server-overlay/wf9-server-overlay/assembly.xml
index e7fcb1b..04b9ca8 100755
--- a/distribution/server-overlay/wf9-server-overlay/assembly.xml
+++ b/distribution/server-overlay/wf9-server-overlay/assembly.xml
@@ -59,6 +59,11 @@
             <destName>standalone-keycloak.xml</destName>
         </file>
         <file>
+            <source>${project.build.directory}/unpacked/keycloak-${project.version}/standalone/configuration/standalone-ha.xml</source>
+            <outputDirectory>standalone/configuration</outputDirectory>
+            <destName>standalone-keycloak-ha.xml</destName>
+        </file>
+        <file>
             <source>${project.build.directory}/unpacked/keycloak-${project.version}/standalone/configuration/keycloak-server.json</source>
             <outputDirectory>standalone/configuration</outputDirectory>
         </file>
diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index d669e6b..556708e 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -167,8 +167,7 @@
             "clientId": "admin-client",
             "enabled": true,
             "publicClient": true,
-            "directGrantsOnly": true,
-            "consentRequired": true
+            "directGrantsOnly": true
         },
         {
             "clientId": "product-sa-client",
diff --git a/examples/js-console/src/main/webapp/index.html b/examples/js-console/src/main/webapp/index.html
index 796aebd..153053b 100644
--- a/examples/js-console/src/main/webapp/index.html
+++ b/examples/js-console/src/main/webapp/index.html
@@ -10,6 +10,7 @@
     <button onclick="refreshToken(9999)">Refresh Token</button>
     <button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
     <button onclick="loadProfile()">Get Profile</button>
+    <button onclick="loadUserInfo()">Get User Info</button>
     <button onclick="output(keycloak.tokenParsed)">Show Token</button>
     <button onclick="output(keycloak.refreshTokenParsed)">Show Refresh Token</button>
     <button onclick="output(keycloak.idTokenParsed)">Show ID Token</button>
@@ -35,6 +36,14 @@
         });
     }
 
+    function loadUserInfo() {
+        keycloak.loadUserInfo().success(function(userInfo) {
+            output(userInfo);
+        }).error(function() {
+            output('Failed to load user info');
+        });
+    }
+
     function refreshToken(minValidity) {
         keycloak.updateToken(minValidity).success(function(refreshed) {
             if (refreshed) {
diff --git a/examples/themes/src/main/resources/theme/logo-example/admin/resources/css/logo.css b/examples/themes/src/main/resources/theme/logo-example/admin/resources/css/logo.css
index c00e814..81ed18e 100755
--- a/examples/themes/src/main/resources/theme/logo-example/admin/resources/css/logo.css
+++ b/examples/themes/src/main/resources/theme/logo-example/admin/resources/css/logo.css
@@ -1,7 +1,4 @@
 
 .navbar-pf .navbar-brand {
-    background: url('../img/red-hat-logo.png') no-repeat 0px 0px;
-    display: block;
-    height: 25px;
-    width: 200px;
+    background: url('../img/red-hat-logo.png') no-repeat 0px 5px;
 }
\ No newline at end of file
diff --git a/examples/themes/src/main/resources/theme/logo-example/admin/resources/img/red-hat-logo.png b/examples/themes/src/main/resources/theme/logo-example/admin/resources/img/red-hat-logo.png
index 7dcf731..0b01b1a 100755
Binary files a/examples/themes/src/main/resources/theme/logo-example/admin/resources/img/red-hat-logo.png and b/examples/themes/src/main/resources/theme/logo-example/admin/resources/img/red-hat-logo.png differ
diff --git a/examples/themes/src/main/resources/theme/logo-example/admin/theme.properties b/examples/themes/src/main/resources/theme/logo-example/admin/theme.properties
index 8cf8245..4bbbf0e 100755
--- a/examples/themes/src/main/resources/theme/logo-example/admin/theme.properties
+++ b/examples/themes/src/main/resources/theme/logo-example/admin/theme.properties
@@ -1,3 +1,3 @@
 parent=keycloak
 import=common/keycloak
-styles=css/styles.css lib/patternfly/css/patternfly.css lib/select2-3.4.1/select2.css css/styles.css css/logo.css
\ No newline at end of file
+styles=lib/patternfly/css/patternfly.css lib/select2-3.4.1/select2.css css/styles.css css/logo.css
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
index 493d9af..61eefd9 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/clients.js
@@ -310,17 +310,23 @@ module.controller('ClientCertificateExportCtrl', function($scope, $location, $ht
             data: $scope.jks,
             headers: {
                 'Content-Type': 'application/json',
-                'Accept': 'client/octet-stream'
+                'Accept': 'application/octet-stream'
             }
         }).success(function(data){
             var blob = new Blob([data], {
-                type: 'client/octet-stream'
+                type: 'application/octet-stream'
             });
             var ext = ".jks";
             if ($scope.jks.format == 'PKCS12') ext = ".p12";
             saveAs(blob, 'keystore' + ext);
-        }).error(function(){
-            Notifications.error("Error downloading.");
+        }).error(function(data) {
+            var errorMsg = 'Error downloading';
+            try {
+                var error = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(data)));
+                errorMsg = error['error_description'] ? error['error_description'] : errorMsg;
+            } catch (err) {
+            }
+            Notifications.error(errorMsg);
         });
     }
 
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
index d0fc0d1..50f01b9 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/authentication-flows.html
@@ -9,7 +9,7 @@
             <th colspan="6" class="kc-table-actions">
                 <div class="dropdown pull-left">
                     <select class="form-control" ng-model="flow"
-                            ng-options="flow.alias for flow in flows"
+                            ng-options="(flow.alias|capitalize) for flow in flows"
                             data-ng-change="setupForm()">
                     </select>
                 </div>
@@ -24,7 +24,7 @@
         <tbody>
         <tr ng-repeat="execution in executions" data-ng-show="executions.length > 0">
             <td ng-show="execution.subFlow"></td>
-            <td><h2>{{execution.referenceType}}</h2></td>
+            <td>{{execution.referenceType|capitalize}}</td>
             <td ng-hide="execution.subFlow"></td>
             <td ng-repeat="choice in execution.requirementChoices">
                 <!--
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
index eff7050..540fa9d 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-saml-keys.html
@@ -30,9 +30,9 @@
             </div>
             <div class="form-group">
                 <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
-                    <button class="btn btn-primary" type="submit" data-ng-click="generateSigningKey()">Generate new keys</button>
-                    <button class="btn btn-primary" type="submit" data-ng-click="importSigningKey()">Import</button>
-                    <button class="btn btn-primary" type="submit" data-ng-hide="!signingKeyInfo.certificate" data-ng-click="exportSigningKey()">Export</button>
+                    <button class="btn btn-default" type="submit" data-ng-click="generateSigningKey()">Generate new keys</button>
+                    <button class="btn btn-default" type="submit" data-ng-click="importSigningKey()">Import</button>
+                    <button class="btn btn-default" type="submit" data-ng-hide="!signingKeyInfo.certificate" data-ng-click="exportSigningKey()">Export</button>
                 </div>
             </div>
         </fieldset>
@@ -56,9 +56,9 @@
             </div>
             <div class="form-group">
                 <div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
-                    <button class="btn btn-primary" type="submit" data-ng-click="generateEncryptionKey()">Generate new keys</button>
-                    <button class="btn btn-primary" type="submit" data-ng-click="importEncryptionKey()">Import</button>
-                    <button class="btn btn-primary" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">Export</button>
+                    <button class="btn btn-default" type="submit" data-ng-click="generateEncryptionKey()">Generate new keys</button>
+                    <button class="btn btn-default" type="submit" data-ng-click="importEncryptionKey()">Import</button>
+                    <button class="btn btn-default" type="submit" data-ng-hide="!encryptionKeyInfo.certificate" data-ng-click="exportEncryptionKey()">Export</button>
                 </div>
             </div>
         </fieldset>
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html
index 03a38d9..29bb4ab 100644
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-service-account-roles.html
@@ -5,8 +5,6 @@
         <li>{{client.clientId}}</li>
     </ol>
 
-    <h1>{{client.clientId|capitalize}}</h1>
-
     <kc-tabs-client></kc-tabs-client>
 
     <h2><span>{{client.clientId}}</span> Service Accounts </h2>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css b/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css
index 30fb25a..e550668 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css
+++ b/forms/common-themes/src/main/resources/theme/keycloak/admin/resources/css/styles.css
@@ -2,15 +2,6 @@ html,body {
     height: 100%;
 }
 
-/**
-.navbar-pf .navbar-brand {
-    background: url('../img/brand.svg') no-repeat 0px 5px;
-    display: block;
-    height: 25px;
-    width: 200px;
-}
-**/
-
 form {
     margin-top: 20px;
 }
@@ -269,15 +260,15 @@ table {
   border-top: none!important;
 }
 
-.navbar-brand{
-  padding: 0!important;
-  height: 56px!important;
+.navbar-pf .navbar-brand {
+  padding: 0;
+  height: 56px;
   line-height: 56px;
-  background-position: center center!important;
-  background-image: url('../img/keyclok-logo.svg')!important;
-  background-size: 148px 36px !important;
-background-repeat: no-repeat;
-  width: 148px!important;
+  background-position: center center;
+  background-image: url('../img/keyclok-logo.svg');
+  background-size: 148px 36px;
+  background-repeat: no-repeat;
+  width: 148px;
 }
 
 .navbar-pf .navbar-utility > li > a{
diff --git a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index 2202009..83776df 100755
--- a/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/sessions-infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -2,6 +2,7 @@ package org.keycloak.models.sessions.infinispan;
 
 import org.infinispan.Cache;
 import org.infinispan.distexec.mapreduce.MapReduceTask;
+import org.jboss.logging.Logger;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.ClientSessionModel;
 import org.keycloak.models.KeycloakSession;
@@ -41,6 +42,8 @@ import java.util.Map;
  */
 public class InfinispanUserSessionProvider implements UserSessionProvider {
 
+    private static final Logger log = Logger.getLogger(InfinispanUserSessionProvider.class);
+
     private final KeycloakSession session;
     private final Cache<String, SessionEntity> sessionCache;
     private final Cache<LoginFailureKey, LoginFailureEntity> loginFailureCache;
@@ -473,6 +476,8 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
         }
 
         public void put(Cache cache, Object key, Object value) {
+            log.tracev("Adding cache operation: {0} on {1}", CacheOperation.ADD, key);
+
             if (tasks.containsKey(key)) {
                 throw new IllegalStateException("Can't add session: task in progress for session");
             } else {
@@ -481,6 +486,8 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
         }
 
         public void replace(Cache cache, Object key, Object value) {
+            log.tracev("Adding cache operation: {0} on {1}", CacheOperation.REPLACE, key);
+
             CacheTask current = tasks.get(key);
             if (current != null) {
                 switch (current.operation) {
@@ -489,7 +496,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
                         current.value = value;
                         return;
                     case REMOVE:
-                        throw new IllegalStateException("Can't remove session: task in progress for session");
+                        return;
                 }
             } else {
                 tasks.put(key, new CacheTask(cache, CacheOperation.REPLACE, key, value));
@@ -497,6 +504,8 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
         }
 
         public void remove(Cache cache, Object key) {
+            log.tracev("Adding cache operation: {0} on {1}", CacheOperation.REMOVE, key);
+
             tasks.put(key, new CacheTask(cache, CacheOperation.REMOVE, key, null));
         }
 
@@ -514,6 +523,8 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
             }
 
             public void execute() {
+                log.tracev("Executing cache operation: {0} on {1}", operation, key);
+
                 switch (operation) {
                     case ADD:
                         cache.put(key, value);
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 f17cc27..f410bec 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
@@ -36,6 +36,7 @@ import org.keycloak.protocol.oidc.TokenManager;
 import org.keycloak.representations.AccessToken;
 import org.keycloak.services.ErrorResponseException;
 import org.keycloak.services.managers.AppAuthManager;
+import org.keycloak.services.managers.AuthenticationManager;
 import org.keycloak.services.resources.Cors;
 import org.keycloak.services.Urls;
 
@@ -117,13 +118,17 @@ public class UserInfoEndpoint {
 
         AccessToken token = null;
         try {
-            token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
+            token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()), true);
         } catch (Exception e) {
             throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Token invalid", Status.FORBIDDEN);
         }
 
         UserSessionModel userSession = session.sessions().getUserSession(realm, token.getSessionState());
         ClientSessionModel clientSession = session.sessions().getClientSession(token.getClientSession());
+        if (userSession == null || clientSession == null || !AuthenticationManager.isSessionValid(realm, userSession)) {
+            throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Token invalid", Status.FORBIDDEN);
+        }
+
         ClientModel clientModel = realm.getClientByClientId(token.getIssuedFor());
         UserModel userModel = userSession.getUser();
         AccessToken userInfo = new AccessToken();
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 03ddcfd..d988aaa 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
@@ -11,6 +11,7 @@ import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.services.ErrorResponseException;
 import org.keycloak.util.CertificateUtils;
 import org.keycloak.util.PemUtils;
 
@@ -21,6 +22,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
 import java.io.ByteArrayOutputStream;
@@ -281,10 +283,10 @@ public class ClientAttributeCertificateResource {
             throw new NotFoundException("keypair not generated for client");
         }
         if (privatePem != null && config.getKeyPassword() == null) {
-            throw new BadRequestException("Need to specify a key password for jks download");
+            throw new ErrorResponseException("password-missing", "Need to specify a key password for jks download", Response.Status.BAD_REQUEST);
         }
         if (config.getStorePassword() == null) {
-            throw new BadRequestException("Need to specify a store password for jks download");
+            throw new ErrorResponseException("password-missing", "Need to specify a store password for jks download", Response.Status.BAD_REQUEST);
         }
         final KeyStore keyStore;
         try {
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index a6888a9..4476557 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -255,6 +255,9 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
         }
 
         ClientSessionModel clientSession = clientCode.getClientSession();
+
+        session.getContext().setClient(clientSession.getClient());
+
         context.getIdp().preprocessFederatedIdentity(session, realmModel, context);
         Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
         if (mappers != null) {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
index 6b739ba..11ced77 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oidc/UserInfoTest.java
@@ -25,6 +25,7 @@ import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.keycloak.OAuth2Constants;
+import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
 import org.keycloak.representations.AccessTokenResponse;
@@ -54,8 +55,6 @@ import static org.junit.Assert.assertNotNull;
  */
 public class UserInfoTest {
 
-    private static RealmModel realm;
-
     @ClassRule
     public static KeycloakRule keycloakRule = new KeycloakRule();
 
@@ -89,6 +88,27 @@ public class UserInfoTest {
     }
 
     @Test
+    public void testSessionExpired() throws Exception {
+        Client client = ClientBuilder.newClient();
+        UriBuilder builder = UriBuilder.fromUri(org.keycloak.testsuite.Constants.AUTH_SERVER_ROOT);
+        URI grantUri = OIDCLoginProtocolService.tokenUrl(builder).build("test");
+        WebTarget grantTarget = client.target(grantUri);
+        AccessTokenResponse accessTokenResponse = executeGrantAccessTokenRequest(grantTarget);
+
+        KeycloakSession session = keycloakRule.startSession();
+        keycloakRule.startSession().sessions().removeUserSessions(session.realms().getRealm("test"));
+        keycloakRule.stopSession(session, true);
+
+        Response response = executeUserInfoRequest(accessTokenResponse.getToken());
+
+        assertEquals(Status.FORBIDDEN.getStatusCode(), response.getStatus());
+
+        response.close();
+
+        client.close();
+    }
+
+    @Test
     public void testUnsuccessfulUserInfoRequest() throws Exception {
         Response response = executeUserInfoRequest("bad");
 
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 277a708..c760152 100755
--- a/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
+++ b/testsuite/integration/src/test/resources/META-INF/keycloak-server.json
@@ -23,15 +23,15 @@
     },
 
     "userSessions": {
-        "provider" : "${keycloak.userSessions.provider:mem}"
+        "provider" : "${keycloak.userSessions.provider:infinispan}"
     },
 
     "realmCache": {
-        "provider": "${keycloak.realm.cache.provider:mem}"
+        "provider": "${keycloak.realm.cache.provider:infinispan}"
     },
 
     "userCache": {
-        "provider": "${keycloak.user.cache.provider:mem}",
+        "provider": "${keycloak.user.cache.provider:infinispan}",
         "mem": {
             "maxSize": 20000
         }