keycloak-aplcache

Merge pull request #2445 from mhajas/js-console-1.9.x-PR KEYCLOAK-2725

3/30/2016 4:16:55 PM

Changes

Details

diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml
index de8ba88..1d8ff36 100644
--- a/testsuite/integration-arquillian/pom.xml
+++ b/testsuite/integration-arquillian/pom.xml
@@ -35,11 +35,11 @@
     <name>Keycloak Arquillian Integration TestSuite</name>
     
     <properties>
-        
+
         <containers.home>${project.build.directory}/containers</containers.home>
         <auth.server.java.home>${java.home}</auth.server.java.home>
         <app.server.java.home>${java.home}</app.server.java.home>
-        
+
         <!--component versions-->
         <arquillian-core.version>1.1.11.Final</arquillian-core.version>
         <selenium.version>2.52.0</selenium.version>
@@ -77,7 +77,7 @@
                 <groupId>org.wildfly</groupId>
                 <artifactId>wildfly-arquillian-container-managed</artifactId>
                 <version>${arquillian-wildfly-container.version}</version>
-            </dependency>        
+            </dependency>
         </dependencies>
     </dependencyManagement>
     
@@ -102,6 +102,7 @@
     <modules>
         <module>servers</module>
         <module>tests</module>
+        <module>test-apps</module>
     </modules>
-    
+
 </project>
diff --git a/testsuite/integration-arquillian/test-apps/js-console/example-realm.json b/testsuite/integration-arquillian/test-apps/js-console/example-realm.json
new file mode 100755
index 0000000..659e5b4
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/js-console/example-realm.json
@@ -0,0 +1,66 @@
+{
+    "realm": "example",
+    "enabled": true,
+    "sslRequired": "external",
+    "registrationAllowed": true,
+    "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" : "user",
+            "enabled": true,
+            "email" : "sample-user@example",
+            "firstName": "Sample",
+            "lastName": "User",
+            "credentials" : [
+                { "type" : "password",
+                  "value" : "password" }
+            ],
+            "realmRoles": [ "user" ],
+            "clientRoles": {
+                "account": ["view-profile", "manage-account"]
+            }
+        }
+    ],
+    "roles" : {
+        "realm" : [
+            {
+                "name": "user",
+                "description": "User privileges"
+            },
+            {
+                "name": "admin",
+                "description": "Administrator privileges"
+            }
+        ]
+    },
+    "scopeMappings": [
+        {
+            "client": "js-console",
+            "roles": ["user"]
+        }
+    ],
+    "clients": [
+        {
+            "clientId": "js-console",
+            "enabled": true,
+            "publicClient": true,
+            "baseUrl": "/js-console",
+            "redirectUris": [
+                "/js-console/*"
+            ],
+            "webOrigins": [
+                "http://localhost:8280"
+            ]
+        }
+    ],
+    "clientScopeMappings": {
+        "account": [
+            {
+                "client": "js-console",
+                "roles": ["view-profile"]
+            }
+        ]
+    }
+}
diff --git a/testsuite/integration-arquillian/test-apps/js-console/pom.xml b/testsuite/integration-arquillian/test-apps/js-console/pom.xml
new file mode 100755
index 0000000..2f1396c
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/js-console/pom.xml
@@ -0,0 +1,52 @@
+<?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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <groupId>org.keycloak.testsuite</groupId>
+        <artifactId>integration-arquillian-test-apps</artifactId>
+        <version>1.9.2.Final-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>integration-arquillian-test-apps-js-console</artifactId>
+    <packaging>war</packaging>
+    <name>JS Console</name>
+    <description/>
+
+    <build>
+        <finalName>js-console</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/testsuite/integration-arquillian/test-apps/js-console/README.md b/testsuite/integration-arquillian/test-apps/js-console/README.md
new file mode 100644
index 0000000..fa9a02d
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/js-console/README.md
@@ -0,0 +1,17 @@
+Basic JavaScript Example
+========================
+
+Start and configure Keycloak
+----------------------------
+
+Start Keycloak:
+
+    bin/standalone.sh
+
+Open the Keycloak admin console, click on Add Realm, click on 'Choose a JSON file', selct example-realm.json and click Upload.
+
+Deploy the JS Console to Keycloak by running:
+
+    mvn install wildfly:deploy
+
+Open the console at http://localhost:8080/js-console and login with username: 'user', and password: 'password'.
diff --git a/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/index.html b/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/index.html
new file mode 100755
index 0000000..1c41fcf
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/index.html
@@ -0,0 +1,156 @@
+<!--
+  ~ 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.
+  -->
+
+<html>
+<head>
+    <script src="http://localhost:8180/auth/js/keycloak.js"></script>
+</head>
+<body>
+
+<div>
+    <button onclick="keycloakInit()">Init</button>
+    <button onclick="keycloak.login()">Login</button>
+    <button onclick="keycloak.logout()">Logout</button>
+    <button onclick="keycloak.register()">Register</button>
+    <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>
+    <button onclick="showExpires()">Show Expires</button>
+    <button onclick="output(keycloak)">Show Details</button>
+    <button onclick="output(keycloak.createLoginUrl())">Show Login URL</button>
+    <button onclick="output(keycloak.createLogoutUrl())">Show Logout URL</button>
+    <button onclick="output(keycloak.createRegisterUrl())">Show Register URL</button>
+    <select id="flowSelect">
+        <option value="standard">standard</option>
+        <option value="implicit">implicit</option>
+    </select>
+
+    <select id="responseModeSelect">
+        <option value="fragment">fragment</option>
+        <option value="query">query</option>
+    </select>
+</div>
+
+<h2>Result</h2>
+<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px;" id="output"></pre>
+
+<h2>Events</h2>
+<pre style="background-color: #ddd; border: 1px solid #ccc; padding: 10px;" id="events"></pre>
+
+
+<script>
+    function loadProfile() {
+        keycloak.loadUserProfile().success(function(profile) {
+            output(profile);
+        }).error(function() {
+            output('Failed to load profile');
+        });
+    }
+
+    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) {
+                output(keycloak.tokenParsed);
+            } else {
+                output('Token not refreshed, valid for ' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds');
+            }
+        }).error(function() {
+            output('Failed to refresh token');
+        });
+    }
+
+    function showExpires() {
+        if (!keycloak.tokenParsed) {
+            output("Not authenticated");
+            return;
+        }
+
+        var o = 'Token Expires:\t\t' + new Date((keycloak.tokenParsed.exp + keycloak.timeSkew) * 1000).toLocaleString() + '\n';
+        o += 'Token Expires in:\t' + Math.round(keycloak.tokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds\n';
+
+        if (keycloak.refreshTokenParsed) {
+            o += 'Refresh Token Expires:\t' + new Date((keycloak.refreshTokenParsed.exp + keycloak.timeSkew) * 1000).toLocaleString() + '\n';
+            o += 'Refresh Expires in:\t' + Math.round(keycloak.refreshTokenParsed.exp + keycloak.timeSkew - new Date().getTime() / 1000) + ' seconds';
+        }
+
+        output(o);
+    }
+
+    function output(data) {
+        if (typeof data === 'object') {
+            data = JSON.stringify(data, null, '  ');
+        }
+        document.getElementById('output').innerHTML = data;
+    }
+
+    function event(event) {
+        var e = document.getElementById('events').innerHTML;
+        document.getElementById('events').innerHTML = new Date().toLocaleString() + "\t" + event + "\n" + e;
+    }
+
+    var keycloak;
+
+    function keycloakInit() {
+        keycloak = Keycloak();
+
+        keycloak.onAuthSuccess = function () {
+            event('Auth Success');
+        };
+
+        keycloak.onAuthError = function () {
+            event('Auth Error');
+        };
+
+        keycloak.onAuthRefreshSuccess = function () {
+            event('Auth Refresh Success');
+        };
+
+        keycloak.onAuthRefreshError = function () {
+            event('Auth Refresh Error');
+        };
+
+        keycloak.onAuthLogout = function () {
+            event('Auth Logout');
+        };
+
+        keycloak.onTokenExpired = function () {
+            event('Access token expired.');
+        };
+
+        var initOptions = {flow: document.getElementById("flowSelect").value, responseMode:  document.getElementById("responseModeSelect").value}
+        keycloak.init(initOptions).success(function (authenticated) {
+            output('Init Success (' + (authenticated ? 'Authenticated' : 'Not Authenticated') + ')');
+        }).error(function () {
+            output('Init Error');
+        });
+    }
+
+</script>
+</body>
+</html>
diff --git a/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/keycloak.json b/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/keycloak.json
new file mode 100644
index 0000000..00f6c9e
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/keycloak.json
@@ -0,0 +1,8 @@
+{
+  "realm" : "example",
+  "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+  "auth-server-url" : "http://localhost:8180/auth",
+  "ssl-required" : "external",
+  "resource" : "js-console",
+  "public-client" : true
+}
diff --git a/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/WEB-INF/web.xml b/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..16e8b23
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,25 @@
+<?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>js-console</module-name>
+</web-app>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/test-apps/pom.xml b/testsuite/integration-arquillian/test-apps/pom.xml
new file mode 100644
index 0000000..e031856
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/pom.xml
@@ -0,0 +1,21 @@
+<?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>1.9.2.Final-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>integration-arquillian-test-apps</artifactId>
+    <packaging>pom</packaging>
+
+    <name>Test apps</name>
+
+    <modules>
+        <module>js-console</module>
+        <module>test-apps-dist</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/test-apps/test-apps-dist/assembly.xml b/testsuite/integration-arquillian/test-apps/test-apps-dist/assembly.xml
new file mode 100644
index 0000000..5fd7363
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/test-apps-dist/assembly.xml
@@ -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.
+  -->
+
+<assembly>
+    <id>test-apps-dist</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <includeBaseDirectory>true</includeBaseDirectory>
+
+    <fileSets>
+        <fileSet>
+            <directory>target/test-apps</directory>
+            <outputDirectory></outputDirectory>
+            <excludes>
+                <exclude>**/pom.xml.releaseBackup</exclude>
+                <exclude>**/.svn/**</exclude>
+                <exclude>**/target/**</exclude>
+                <exclude>**/*.iml</exclude>
+            </excludes>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/testsuite/integration-arquillian/test-apps/test-apps-dist/build.xml b/testsuite/integration-arquillian/test-apps/test-apps-dist/build.xml
new file mode 100755
index 0000000..e48e088
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/test-apps-dist/build.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ 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 name="test-apps-dist" basedir="." default="all">
+
+    <target name="all">
+        <delete dir="target/test-apps"/>
+        <copy todir="target/test-apps/js-console" overwrite="true">
+            <fileset dir="../js-console">
+                <exclude name="**/target/**"/>
+                <exclude name="**/*.iml"/>
+                <exclude name="**/*.unconfigured"/>
+                <exclude name="**/subsystem-config.xml"/>
+            </fileset>
+        </copy>
+    </target>
+</project>
diff --git a/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml b/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml
new file mode 100644
index 0000000..a518ebe
--- /dev/null
+++ b/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml
@@ -0,0 +1,85 @@
+<?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-test-apps</artifactId>
+        <groupId>org.keycloak.testsuite</groupId>
+        <version>1.9.2.Final-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>integration-arquillian-test-apps-dist</artifactId>
+
+    <name>Test apps distribution</name>
+
+    <build>
+        <finalName>${product.name}-${product.version}-test-apps</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <version>2.8.2</version>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>1.8</version>
+                <inherited>false</inherited>
+                <executions>
+                    <execution>
+                        <id>build-test-apps</id>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <phase>compile</phase>
+                        <configuration>
+                            <target>
+                                <ant antfile="build.xml" inheritRefs="true">
+                                    <target name="all"></target>
+                                </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>
+                </dependencies>
+            </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>
+                <version>2.5.5</version>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/JSConsoleExample.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/JSConsoleExample.java
old mode 100644
new mode 100755
index dff81a0..15f0308
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/JSConsoleExample.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/JSConsoleExample.java
@@ -22,6 +22,7 @@ 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 org.openqa.selenium.support.ui.Select;
 
 import java.net.URL;
 
@@ -32,7 +33,7 @@ import java.net.URL;
 public class JSConsoleExample extends AbstractPageWithInjectedUrl {
 
     public static final String DEPLOYMENT_NAME = "js-console-example";
-    public static final String CLIENT_ID = "js-console";
+    public static final String CLIENT_ID = "integration-arquillian-test-apps-js-console";
 
     @ArquillianResource
     @OperateOnDeployment(DEPLOYMENT_NAME)
@@ -45,6 +46,8 @@ public class JSConsoleExample extends AbstractPageWithInjectedUrl {
         return fixedUrl != null ? fixedUrl : url;
     }
 
+    @FindBy(xpath = "//button[text() = 'Init']")
+    private WebElement initButton;
     @FindBy(xpath = "//button[text() = 'Login']")
     private WebElement logInButton;
     @FindBy(xpath = "//button[text() = 'Logout']")
@@ -67,6 +70,17 @@ public class JSConsoleExample extends AbstractPageWithInjectedUrl {
     @FindBy(xpath = "//button[text() = 'Show Details']")
     private WebElement showDetailsButton;
 
+    @FindBy(id = "flowSelect")
+    private Select flowSelect;
+    @FindBy(id = "responseModeSelect")
+    private Select responseModeSelect;
+
+    @FindBy(id = "output")
+    private WebElement outputArea;
+
+    @FindBy(id = "events")
+    private WebElement eventsArea;
+
     public void logIn() {
         logInButton.click();
     }
@@ -87,4 +101,23 @@ public class JSConsoleExample extends AbstractPageWithInjectedUrl {
         getProfileButton.click();
     }
 
+    public void setFlow(String value) {
+        flowSelect.selectByValue(value);
+    }
+
+    public void init() {
+        initButton.click();
+    }
+
+    public void setResponseMode(String value) {
+        responseModeSelect.selectByValue(value);
+    }
+
+    public String getOutputText() {
+        return outputArea.getText();
+    }
+
+    public String getEventsText() {
+        return eventsArea.getText();
+    }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java
index 3a5012a..9e7f4f1 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractExampleAdapterTest.java
@@ -38,6 +38,7 @@ public abstract class AbstractExampleAdapterTest extends AbstractAdapterTest {
     public static final String EXAMPLES_HOME;
     public static final String EXAMPLES_VERSION_SUFFIX;
     public static final String EXAMPLES_HOME_DIR;
+    public static final String TEST_APPS_HOME_DIR;
     public static final String EXAMPLES_WEB_XML;
 
     static {
@@ -49,7 +50,13 @@ public abstract class AbstractExampleAdapterTest extends AbstractAdapterTest {
         Assert.assertNotNull("Property ${examples.version.suffix} must bet set.", EXAMPLES_VERSION_SUFFIX);
         System.out.println(EXAMPLES_VERSION_SUFFIX);
 
-        EXAMPLES_HOME_DIR = EXAMPLES_HOME + "/keycloak-examples-" + EXAMPLES_VERSION_SUFFIX;
+        if (!System.getProperty("unpacked.container.folder.name","").isEmpty()) {
+            EXAMPLES_HOME_DIR = EXAMPLES_HOME + "/" + System.getProperty("unpacked.container.folder.name","") + "-examples";
+            TEST_APPS_HOME_DIR = EXAMPLES_HOME + "/" + System.getProperty("unpacked.container.folder.name","") + "-test-apps";
+        } else {
+            EXAMPLES_HOME_DIR = EXAMPLES_HOME + "/keycloak-examples-" + EXAMPLES_VERSION_SUFFIX;
+            TEST_APPS_HOME_DIR = EXAMPLES_HOME + "/Keycloak-" + EXAMPLES_VERSION_SUFFIX + "-test-apps";
+        }
 
         EXAMPLES_WEB_XML = EXAMPLES_HOME + "/web.xml";
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractJSConsoleExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractJSConsoleExampleAdapterTest.java
old mode 100644
new mode 100755
index 3251c34..e4c9226
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractJSConsoleExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/AbstractJSConsoleExampleAdapterTest.java
@@ -73,7 +73,7 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
 
     @Override
     public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
-        RealmRepresentation jsConsoleRealm = loadRealm(new File(EXAMPLES_HOME_DIR + "/js-console/example-realm.json"));
+        RealmRepresentation jsConsoleRealm = loadRealm(new File(TEST_APPS_HOME_DIR + "/js-console/example-realm.json"));
 
         fixClientUrisUsingDeploymentUrl(jsConsoleRealm,
                 JSConsoleExample.CLIENT_ID, jsConsoleExamplePage.buildUri().toASCIIString());
@@ -96,6 +96,7 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
 
         pause(1000);
 
+        jsConsoleExamplePage.init();
         jsConsoleExamplePage.logIn();
         testRealmLoginPage.form().login("user", "invalid-password");
         assertCurrentUrlDoesntStartWith(jsConsoleExamplePage);
@@ -105,14 +106,17 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
 
         testRealmLoginPage.form().login("user", "password");
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
-        assertTrue(driver.getPageSource().contains("Init Success (Authenticated)"));
-        assertTrue(driver.getPageSource().contains("Auth Success"));
+        jsConsoleExamplePage.init();
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Init Success (Authenticated)"));
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Auth Success"));
 
         pause(1000);
 
         jsConsoleExamplePage.logOut();
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
-        assertTrue(driver.getPageSource().contains("Init Success (Not Authenticated)"));
+        jsConsoleExamplePage.init();
+
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Init Success (Not Authenticated)"));
     }
 
     @Test
@@ -120,38 +124,41 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
         jsConsoleExamplePage.navigateTo();
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
 
+        jsConsoleExamplePage.init();
         jsConsoleExamplePage.refreshToken();
-        assertTrue(driver.getPageSource().contains("Failed to refresh token"));
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Failed to refresh token"));
 
         jsConsoleExamplePage.logIn();
         testRealmLoginPage.form().login("user", "password");
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
-        assertTrue(driver.getPageSource().contains("Auth Success"));
+        jsConsoleExamplePage.init();
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Auth Success"));
 
         jsConsoleExamplePage.refreshToken();
-        assertTrue(driver.getPageSource().contains("Auth Refresh Success"));
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Auth Refresh Success"));
     }
 
     @Test
     public void testRefreshTokenIfUnder30s() {
         jsConsoleExamplePage.navigateTo();
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
-
+        jsConsoleExamplePage.init();
         jsConsoleExamplePage.refreshToken();
-        assertTrue(driver.getPageSource().contains("Failed to refresh token"));
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Failed to refresh token"));
 
         jsConsoleExamplePage.logIn();
         testRealmLoginPage.form().login("user", "password");
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
-        assertTrue(driver.getPageSource().contains("Auth Success"));
+        jsConsoleExamplePage.init();
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Auth Success"));
 
         jsConsoleExamplePage.refreshTokenIfUnder30s();
-        assertTrue(driver.getPageSource().contains("Token not refreshed, valid for"));
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Token not refreshed, valid for"));
 
         pause((TOKEN_LIFESPAN_LEEWAY + 2) * 1000);
 
         jsConsoleExamplePage.refreshTokenIfUnder30s();
-        assertTrue(driver.getPageSource().contains("Auth Refresh Success"));
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Auth Refresh Success"));
     }
 
     @Test
@@ -159,17 +166,18 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
         jsConsoleExamplePage.navigateTo();
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
 
+        jsConsoleExamplePage.init();
         jsConsoleExamplePage.getProfile();
-        assertTrue(driver.getPageSource().contains("Failed to load profile"));
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Failed to load profile"));
 
         jsConsoleExamplePage.logIn();
         testRealmLoginPage.form().login("user", "password");
         assertCurrentUrlStartsWith(jsConsoleExamplePage);
-        assertTrue(driver.getPageSource().contains("Auth Success"));
+        jsConsoleExamplePage.init();
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Auth Success"));
 
         jsConsoleExamplePage.getProfile();
-        assertTrue(driver.getPageSource().contains("Failed to load profile"));
-        assertTrue(driver.getPageSource().contains("\"username\": \"user\""));
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("\"username\": \"user\""));
     }
 
     @Test
@@ -194,6 +202,7 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
         testRealmResource().update(realm);
 
         jsConsoleExamplePage.navigateTo();
+        jsConsoleExamplePage.init();
         jsConsoleExamplePage.logIn();
 
         testRealmLoginPage.form().login("user", "password");
@@ -201,12 +210,14 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
         assertTrue(oAuthGrantPage.isCurrent());
         oAuthGrantPage.accept();
 
-        assertTrue(driver.getPageSource().contains("Init Success (Authenticated)"));
+        jsConsoleExamplePage.init();
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Init Success (Authenticated)"));
 
         applicationsPage.navigateTo();
         applicationsPage.revokeGrantForApplication("js-console");
 
         jsConsoleExamplePage.navigateTo();
+        jsConsoleExamplePage.init();
         jsConsoleExamplePage.logIn();
 
         assertTrue(oAuthGrantPage.isCurrent());
@@ -223,7 +234,7 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
 
         resultList.get(0).findElement(By.xpath(".//td[text()='REVOKE_GRANT']"));
         resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='account']"));
-        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
         resultList.get(0).findElement(By.xpath(".//td[text()='revoked_client']/../td[text()='js-console']"));
 
         loginEventsPage.table().reset();
@@ -235,9 +246,87 @@ public abstract class AbstractJSConsoleExampleAdapterTest extends AbstractExampl
 
         resultList.get(0).findElement(By.xpath(".//td[text()='LOGIN']"));
         resultList.get(0).findElement(By.xpath(".//td[text()='Client']/../td[text()='js-console']"));
-        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1']"));
+        resultList.get(0).findElement(By.xpath(".//td[text()='IP Address']/../td[text()='127.0.0.1' or text()='0:0:0:0:0:0:0:1']"));
         resultList.get(0).findElement(By.xpath(".//td[text()='username']/../td[text()='user']"));
         resultList.get(0).findElement(By.xpath(".//td[text()='consent']/../td[text()='consent_granted']"));
     }
 
+
+    @Test
+    public void implicitFlowTest() {
+        jsConsoleExamplePage.navigateTo();
+        jsConsoleExamplePage.setFlow("implicit");
+        jsConsoleExamplePage.init();
+
+        jsConsoleExamplePage.logIn();
+        assertTrue(driver.getPageSource().contains("Implicit flow is disabled for the client"));
+
+        setImplicitFlowFroClient();
+
+        jsConsoleExamplePage.navigateTo();
+        jsConsoleExamplePage.init();
+        jsConsoleExamplePage.logIn();
+        assertTrue(driver.getPageSource().contains("Standard flow is disabled for the client"));
+
+        logInAndInit("implicit");
+
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Init Success (Authenticated)"));
+    }
+
+    @Test
+    public void implicitFlowQueryTest() {
+        setImplicitFlowFroClient();
+
+        jsConsoleExamplePage.navigateTo();
+        jsConsoleExamplePage.setFlow("implicit");
+        jsConsoleExamplePage.setResponseMode("query");
+        jsConsoleExamplePage.init();
+        jsConsoleExamplePage.logIn();
+        assertTrue(driver.getPageSource().contains("Invalid parameter: response_mode"));
+    }
+
+    @Test
+    public void implicitFlowRefreshTokenTest() {
+        setImplicitFlowFroClient();
+
+        logInAndInit("implicit");
+
+        jsConsoleExamplePage.refreshToken();
+
+        assertTrue(jsConsoleExamplePage.getOutputText().contains("Failed to refresh token"));
+    }
+
+    @Test
+    public void implicitFlowOnTokenExpireTest() {
+        RealmRepresentation realm = testRealmResource().toRepresentation();
+        realm.setAccessTokenLifespanForImplicitFlow(5);
+        testRealmResource().update(realm);
+
+        setImplicitFlowFroClient();
+
+        logInAndInit("implicit");
+
+        pause(5000);
+
+        assertTrue(jsConsoleExamplePage.getEventsText().contains("Access token expired"));
+    }
+
+    private void setImplicitFlowFroClient() {
+        ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "js-console");
+        ClientRepresentation client = clientResource.toRepresentation();
+        client.setImplicitFlowEnabled(true);
+        client.setStandardFlowEnabled(false);
+        clientResource.update(client);
+    }
+
+    private void logInAndInit(String flow) {
+        jsConsoleExamplePage.navigateTo();
+        jsConsoleExamplePage.setFlow(flow);
+        jsConsoleExamplePage.init();
+        jsConsoleExamplePage.logIn();
+        testRealmLoginPage.form().login("user", "password");
+        jsConsoleExamplePage.setFlow(flow);
+        jsConsoleExamplePage.init();
+    }
+
 }
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPJSConsoleExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPJSConsoleExampleAdapterTest.java
new file mode 100644
index 0000000..0674eea
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/example/EAPJSConsoleExampleAdapterTest.java
@@ -0,0 +1,13 @@
+package org.keycloak.testsuite.adapter.example;
+
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+import org.junit.Ignore;
+/**
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-eap")
+//@AdapterLibsLocationProperty("adapter.libs.eap")
+public class EAPJSConsoleExampleAdapterTest extends AbstractJSConsoleExampleAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6JSConsoleExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6JSConsoleExampleAdapterTest.java
index 20bd52e..4f167ba 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6JSConsoleExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/example/EAP6JSConsoleExampleAdapterTest.java
@@ -1,5 +1,6 @@
 package org.keycloak.testsuite.adapter.example;
 
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
 import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
 import org.junit.Ignore;
 /**
@@ -7,7 +8,6 @@ import org.junit.Ignore;
  */
 @AppServerContainer("app-server-eap6")
 //@AdapterLibsLocationProperty("adapter.libs.eap6")
-@Ignore //jsconsole example has hardcoded relative path to keycloak.js
 public class EAP6JSConsoleExampleAdapterTest extends AbstractJSConsoleExampleAdapterTest {
 
 }
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyJSConsoleExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyJSConsoleExampleAdapterTest.java
new file mode 100644
index 0000000..7834461
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/example/WildflyJSConsoleExampleAdapterTest.java
@@ -0,0 +1,16 @@
+
+package org.keycloak.testsuite.adapter.example;
+
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-wildfly")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class WildflyJSConsoleExampleAdapterTest extends AbstractJSConsoleExampleAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
index f46954a..a2e20fd 100644
--- a/testsuite/integration-arquillian/tests/other/adapters/pom.xml
+++ b/testsuite/integration-arquillian/tests/other/adapters/pom.xml
@@ -220,8 +220,8 @@
                                                 <type>war</type>
                                             </artifactItem>       
                                             <artifactItem>
-                                                <groupId>org.keycloak.example.demo</groupId>
-                                                <artifactId>js-console</artifactId>        
+                                                <groupId>org.keycloak.testsuite</groupId>
+                                                <artifactId>integration-arquillian-test-apps-js-console</artifactId>
                                                 <version>${project.version}</version>
                                                 <type>war</type>
                                             </artifactItem>
@@ -287,6 +287,13 @@
                                                 <type>zip</type>
                                                 <includes>**/*realm.json,**/testsaml.json</includes>
                                             </artifactItem>
+                                            <artifactItem>
+                                                <groupId>org.keycloak.testsuite</groupId>
+                                                <artifactId>integration-arquillian-test-apps-dist</artifactId>
+                                                <version>${project.version}</version>
+                                                <type>zip</type>
+                                                <includes>**/*realm.json,**/testsaml.json</includes>
+                                            </artifactItem>
                                         </artifactItems>
                                         <outputDirectory>${examples.home}</outputDirectory>
                                         <overWriteIfNewer>true</overWriteIfNewer>