Merge pull request #2444 from mhajas/js-console-up-PR
KEYCLOAK-2725 Run js-console example on non-relative scanario + tests of implicit flow
This commit is contained in:
commit
3d3d526e30
18 changed files with 694 additions and 28 deletions
|
@ -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>
|
||||
|
|
|
@ -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'.
|
66
testsuite/integration-arquillian/test-apps/js-console/example-realm.json
Executable file
66
testsuite/integration-arquillian/test-apps/js-console/example-realm.json
Executable file
|
@ -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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
52
testsuite/integration-arquillian/test-apps/js-console/pom.xml
Executable file
52
testsuite/integration-arquillian/test-apps/js-console/pom.xml
Executable file
|
@ -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>2.0.0.CR1-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>
|
|
@ -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>
|
156
testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/index.html
Executable file
156
testsuite/integration-arquillian/test-apps/js-console/src/main/webapp/index.html
Executable file
|
@ -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>
|
|
@ -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
|
||||
}
|
21
testsuite/integration-arquillian/test-apps/pom.xml
Normal file
21
testsuite/integration-arquillian/test-apps/pom.xml
Normal file
|
@ -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>2.0.0.CR1-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>
|
|
@ -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>
|
31
testsuite/integration-arquillian/test-apps/test-apps-dist/build.xml
Executable file
31
testsuite/integration-arquillian/test-apps/test-apps-dist/build.xml
Executable file
|
@ -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>
|
|
@ -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>2.0.0.CR1-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>
|
35
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/JSConsoleExample.java
Normal file → Executable file
35
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/JSConsoleExample.java
Normal file → Executable file
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue