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:
Bill Burke 2016-03-30 15:16:50 -04:00
commit 3d3d526e30
18 changed files with 694 additions and 28 deletions

View file

@ -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>

View file

@ -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'.

View 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"]
}
]
}
}

View 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>

View file

@ -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>

View 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>

View file

@ -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
}

View 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>

View file

@ -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>

View 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>

View file

@ -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>

View 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();
}
}

View file

@ -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";
}

View file

@ -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();
}
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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 {
}

View file

@ -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>