keycloak-memoizeit
Changes
pom.xml 15(+15 -0)
testsuite/pom.xml 190(+190 -0)
testsuite/src/test/resources/app-web.xml 27(+27 -0)
testsuite/src/test/resources/persistence.xml 33(+33 -0)
testsuite/src/test/resources/testrealm.json 76(+76 -0)
testsuite/src/test/resources/user.jsp 14(+14 -0)
testsuite/src/test/resources/web.xml 39(+39 -0)
Details
pom.xml 15(+15 -0)
diff --git a/pom.xml b/pom.xml
index f937a7d..39e3315 100755
--- a/pom.xml
+++ b/pom.xml
@@ -210,6 +210,21 @@
<artifactId>javase</artifactId>
<version>2.2</version>
</dependency>
+
+ <dependency>
+ <groupId>org.jboss.arquillian</groupId>
+ <artifactId>arquillian-bom</artifactId>
+ <version>1.1.1.Final</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.extension</groupId>
+ <artifactId>arquillian-drone-bom</artifactId>
+ <version>1.2.0.Alpha3</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
testsuite/pom.xml 190(+190 -0)
diff --git a/testsuite/pom.xml b/testsuite/pom.xml
new file mode 100755
index 0000000..523bbf1
--- /dev/null
+++ b/testsuite/pom.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0"?>
+<project>
+ <parent>
+ <artifactId>keycloak-parent</artifactId>
+ <groupId>org.keycloak</groupId>
+ <version>1.0-alpha-1</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>keycloak-testsuite</artifactId>
+ <name>Keycloak TestSuite</name>
+ <description />
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-as7-adapter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>jose-jwt</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-services</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-social-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-social-google</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-social-twitter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-social-facebook</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-forms</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-idm-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-idm-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-idm-simple-schema</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.picketlink</groupId>
+ <artifactId>picketlink-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>jaxrs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>1.3.161</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.junit</groupId>
+ <artifactId>arquillian-junit-container</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.extension</groupId>
+ <artifactId>arquillian-drone-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.extension</groupId>
+ <artifactId>arquillian-drone-selenium</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.arquillian.extension</groupId>
+ <artifactId>arquillian-drone-selenium-server</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-java</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-server</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>servlet-api-2.5</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>jboss-managed</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-arquillian-container-managed</artifactId>
+ <scope>test</scope>
+ <version>7.1.1.Final</version>
+ </dependency>
+ </dependencies>
+ </profile>
+ <profile>
+ <id>jboss-remote</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.as</groupId>
+ <artifactId>jboss-as-arquillian-container-remote</artifactId>
+ <scope>test</scope>
+ <version>7.1.1.Final</version>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+</project>
diff --git a/testsuite/src/test/java/org/keycloak/testsuite/AbstractDroneTest.java b/testsuite/src/test/java/org/keycloak/testsuite/AbstractDroneTest.java
new file mode 100644
index 0000000..eecc84a
--- /dev/null
+++ b/testsuite/src/test/java/org/keycloak/testsuite/AbstractDroneTest.java
@@ -0,0 +1,154 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+
+import com.thoughtworks.selenium.DefaultSelenium;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public abstract class AbstractDroneTest {
+
+ @Deployment(name = "app", testable = false, order = 2)
+ public static WebArchive appDeployment() {
+ File[] libs = Maven.resolver().loadPomFromFile("pom.xml")
+ .resolve("org.keycloak:keycloak-core", "org.keycloak:keycloak-as7-adapter").withoutTransitivity().asFile();
+
+ WebArchive archive = ShrinkWrap.create(WebArchive.class, "app.war").addClasses(TestApplication.class)
+ .addAsLibraries(libs).addAsWebInfResource("jboss-deployment-structure.xml")
+ .addAsWebInfResource("app-web.xml", "web.xml").addAsWebInfResource("app-jboss-web.xml", "jboss-web.xml")
+ .addAsWebInfResource("app-resteasy-oauth.json", "resteasy-oauth.json").addAsWebResource("user.jsp");
+ return archive;
+ }
+
+ @Deployment(name = "auth-server", testable = false, order = 1)
+ public static WebArchive deployment() {
+ File[] libs = Maven.resolver().loadPomFromFile("pom.xml").importRuntimeDependencies().resolve().withTransitivity()
+ .asFile();
+
+ WebArchive archive = ShrinkWrap.create(WebArchive.class, "auth-server.war").addClasses(TestApplication.class)
+ .addAsLibraries(libs).addAsWebInfResource("jboss-deployment-structure.xml").addAsWebInfResource("web.xml")
+ .addAsResource("persistence.xml", "META-INF/persistence.xml")
+ .addAsResource("testrealm.json", "META-INF/testrealm.json");
+
+ return archive;
+ }
+
+ URL appUrl;
+
+ URL authServerUrl;
+
+ String DEFAULT_WAIT = "10000";
+
+ @Drone
+ DefaultSelenium selenium;
+
+ @After
+ public void after() {
+ logout();
+ }
+
+ @Before
+ public void before() throws MalformedURLException {
+ authServerUrl = new URL("http://localhost:8080/auth-server");
+ appUrl = new URL("http://localhost:8080/app/user.jsp");
+ }
+
+ public void login(String username, String password) {
+ login(username, password, null);
+ }
+
+ public void login(String username, String password, String expectErrorMessage) {
+ selenium.open(appUrl.toString());
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ Assert.assertEquals("Log in to demo", selenium.getTitle());
+
+ if (username != null) {
+ selenium.type("id=username", username);
+ }
+
+ if (password != null) {
+ selenium.type("id=password", password);
+ }
+
+ selenium.click("css=input[type=\"submit\"]");
+
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ if (expectErrorMessage == null) {
+ Assert.assertEquals(username, selenium.getText("id=user"));
+ } else {
+ Assert.assertTrue(selenium.isTextPresent(expectErrorMessage));
+ }
+ }
+
+ public void logout() {
+ selenium.open(authServerUrl + "/rest/realms/demo/tokens/logout?redirect_uri=" + appUrl);
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ Assert.assertEquals("Log in to demo", selenium.getTitle());
+ }
+
+ public void registerUser(String username, String password) {
+ registerUser(username, password, null);
+ }
+
+ public void registerUser(String username, String password, String expectErrorMessage) {
+ selenium.open(appUrl.toString());
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ selenium.click("link=Register");
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+ selenium.type("id=name", "Test User");
+ selenium.type("id=email", "test@user.com");
+ if (username != null) {
+ selenium.type("id=username", username);
+ }
+ if (password != null) {
+ selenium.type("id=password", password);
+ selenium.type("id=password-confirm", password);
+ }
+ selenium.click("css=input[type=\"submit\"]");
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ if (expectErrorMessage == null) {
+ Assert.assertEquals(username, selenium.getText("id=user"));
+ } else {
+ Assert.assertTrue(selenium.isTextPresent(expectErrorMessage));
+ }
+ }
+
+}
diff --git a/testsuite/src/test/java/org/keycloak/testsuite/LoginTest.java b/testsuite/src/test/java/org/keycloak/testsuite/LoginTest.java
new file mode 100644
index 0000000..fab2d16
--- /dev/null
+++ b/testsuite/src/test/java/org/keycloak/testsuite/LoginTest.java
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite;
+
+import org.jboss.arquillian.junit.Arquillian;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@RunWith(Arquillian.class)
+public class LoginTest extends AbstractDroneTest {
+
+ @Test
+ public void loginInvalidPassword() {
+ login("invalid", "password", "Invalid username or password");
+ }
+
+ @Test
+ public void loginInvalidUsername() {
+ login("invalid", "password", "Invalid username or password");
+ }
+
+ @Test
+ public void loginSuccess() {
+ login("bburke@redhat.com", "password");
+ }
+
+}
diff --git a/testsuite/src/test/java/org/keycloak/testsuite/RegisterTest.java b/testsuite/src/test/java/org/keycloak/testsuite/RegisterTest.java
new file mode 100644
index 0000000..96cf70d
--- /dev/null
+++ b/testsuite/src/test/java/org/keycloak/testsuite/RegisterTest.java
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite;
+
+import org.jboss.arquillian.junit.Arquillian;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@RunWith(Arquillian.class)
+public class RegisterTest extends AbstractDroneTest {
+
+ @Test
+ public void registerUserMissingPassword() {
+ registerUser("registerUserMissingPassword", null, "Please specify password");
+ }
+
+ @Test
+ public void registerUserMissingUsername() {
+ registerUser(null, "password", "Please specify username");
+ }
+
+ @Test
+ public void registerUserSuccess() {
+ registerUser("registerUserSuccess", "password");
+ }
+
+}
diff --git a/testsuite/src/test/java/org/keycloak/testsuite/TestApplication.java b/testsuite/src/test/java/org/keycloak/testsuite/TestApplication.java
new file mode 100755
index 0000000..0b1dcf5
--- /dev/null
+++ b/testsuite/src/test/java/org/keycloak/testsuite/TestApplication.java
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.jboss.resteasy.jwt.JsonSerialization;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.managers.RealmManager;
+import org.keycloak.services.models.KeycloakSession;
+import org.keycloak.services.models.RealmModel;
+import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.resources.SaasService;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class TestApplication extends KeycloakApplication {
+
+ public static RealmRepresentation loadJson(String path)
+ {
+ InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ int c;
+ try {
+ while ( (c = is.read()) != -1)
+ {
+ os.write(c);
+ }
+ byte[] bytes = os.toByteArray();
+ //System.out.println(new String(bytes));
+
+ return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public TestApplication() {
+ super();
+ KeycloakSession session = factory.createSession();
+ session.getTransaction().begin();
+ RealmManager realmManager = new RealmManager(session);
+ if (realmManager.defaultRealm() == null) {
+ install(realmManager);
+ }
+ session.getTransaction().commit();
+ }
+
+ public void install(RealmManager manager) {
+ RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
+ defaultRealm.setName(RealmModel.DEFAULT_REALM);
+ defaultRealm.setEnabled(true);
+ defaultRealm.setTokenLifespan(300);
+ defaultRealm.setAccessCodeLifespan(60);
+ defaultRealm.setSslNotRequired(true);
+ defaultRealm.setCookieLoginAllowed(true);
+ defaultRealm.setRegistrationAllowed(true);
+ manager.generateRealmKeys(defaultRealm);
+ defaultRealm.addRequiredCredential(CredentialRepresentation.PASSWORD);
+ defaultRealm.addRole(SaasService.REALM_CREATOR_ROLE);
+ defaultRealm.addDefaultRole(SaasService.REALM_CREATOR_ROLE);
+
+ RealmRepresentation rep = loadJson("META-INF/testrealm.json");
+ RealmModel realm = manager.createRealm("demo", rep.getRealm());
+ manager.importRealm(rep, realm);
+
+ }
+
+
+}
diff --git a/testsuite/src/test/java/org/keycloak/testsuite/TotpTest.java b/testsuite/src/test/java/org/keycloak/testsuite/TotpTest.java
new file mode 100644
index 0000000..ca557f1
--- /dev/null
+++ b/testsuite/src/test/java/org/keycloak/testsuite/TotpTest.java
@@ -0,0 +1,115 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite;
+
+import java.net.MalformedURLException;
+
+import org.jboss.arquillian.junit.Arquillian;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.picketlink.idm.credential.util.TimeBasedOTP;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@RunWith(Arquillian.class)
+public class TotpTest extends AbstractDroneTest {
+
+ private TimeBasedOTP totp;
+ private String totpSecret;
+
+ @Before
+ public void before() throws MalformedURLException {
+ super.before();
+
+ totp = new TimeBasedOTP();
+ }
+
+ public void configureTotp() {
+ selenium.open(authServerUrl + "/rest/realms/demo/account/totp");
+ selenium.waitForPageToLoad("10000");
+
+ Assert.assertTrue(selenium.isTextPresent("To setup Google Authenticator"));
+
+ totpSecret = selenium.getValue("totpSecret");
+ String code = totp.generate(totpSecret);
+
+ selenium.type("id=totp", code);
+ selenium.click("css=input[type=\"submit\"]");
+ selenium.waitForPageToLoad("30000");
+
+ Assert.assertTrue(selenium.isTextPresent("Google Authenticator enabled"));
+ }
+
+ @Test
+ public void loginWithTotpFailure() {
+ registerUser("loginWithTotpFailure", "password");
+ configureTotp();
+ logout();
+
+ selenium.type("id=username", "loginWithTotpFailure");
+ selenium.type("id=password", "password");
+
+ selenium.click("css=input[type=\"submit\"]");
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ Assert.assertEquals("Log in to demo", selenium.getTitle());
+
+ selenium.type("id=totp", "123456");
+
+ selenium.click("css=input[type=\"submit\"]");
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ Assert.assertTrue(selenium.isTextPresent("Invalid username or password"));
+ }
+
+ @Test
+ public void loginWithTotpSuccess() {
+ registerUser("loginWithTotpSuccess", "password");
+ configureTotp();
+ logout();
+
+ selenium.type("id=username", "loginWithTotpSuccess");
+ selenium.type("id=password", "password");
+
+ selenium.click("css=input[type=\"submit\"]");
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ Assert.assertEquals("Log in to demo", selenium.getTitle());
+
+ selenium.type("id=totp", totp.generate(totpSecret));
+
+ selenium.click("css=input[type=\"submit\"]");
+ selenium.waitForPageToLoad(DEFAULT_WAIT);
+
+ Assert.assertEquals("loginWithTotpSuccess", selenium.getText("id=user"));
+ }
+
+ @Test
+ public void setupTotp() {
+ registerUser("setupTotp", "password");
+ configureTotp();
+ }
+
+}
diff --git a/testsuite/src/test/resources/app-jboss-web.xml b/testsuite/src/test/resources/app-jboss-web.xml
new file mode 100755
index 0000000..3cec19c
--- /dev/null
+++ b/testsuite/src/test/resources/app-jboss-web.xml
@@ -0,0 +1,5 @@
+<jboss-web>
+ <valve>
+ <class-name>org.keycloak.adapters.as7.OAuthManagedResourceValve</class-name>
+ </valve>
+</jboss-web>
\ No newline at end of file
diff --git a/testsuite/src/test/resources/app-resteasy-oauth.json b/testsuite/src/test/resources/app-resteasy-oauth.json
new file mode 100755
index 0000000..a36b5cf
--- /dev/null
+++ b/testsuite/src/test/resources/app-resteasy-oauth.json
@@ -0,0 +1,11 @@
+{
+ "realm" : "demo",
+ "resource" : "customer-portal",
+ "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+ "auth-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/login",
+ "code-url" : "http://localhost:8080/auth-server/rest/realms/demo/tokens/access/codes",
+ "ssl-not-required" : true,
+ "credentials" : {
+ "password" : "password"
+ }
+}
testsuite/src/test/resources/app-web.xml 27(+27 -0)
diff --git a/testsuite/src/test/resources/app-web.xml b/testsuite/src/test/resources/app-web.xml
new file mode 100755
index 0000000..4ab9fac
--- /dev/null
+++ b/testsuite/src/test/resources/app-web.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>app</module-name>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Customers</web-resource-name>
+ <url-pattern>/user.jsp</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>user</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>commerce</realm-name>
+ </login-config>
+
+ <security-role>
+ <role-name>user</role-name>
+ </security-role>
+</web-app>
diff --git a/testsuite/src/test/resources/arquillian.xml b/testsuite/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..378dfed
--- /dev/null
+++ b/testsuite/src/test/resources/arquillian.xml
@@ -0,0 +1,9 @@
+<arquillian xmlns="http://jboss.org/schema/arquillian"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+ <extension qualifier="selenium">
+ <property name="browser">*googlechrome</property>
+ </extension>
+</arquillian>
\ No newline at end of file
diff --git a/testsuite/src/test/resources/jboss-deployment-structure.xml b/testsuite/src/test/resources/jboss-deployment-structure.xml
new file mode 100755
index 0000000..b4aedd4
--- /dev/null
+++ b/testsuite/src/test/resources/jboss-deployment-structure.xml
@@ -0,0 +1,12 @@
+<jboss-deployment-structure>
+ <deployment>
+ <!-- This allows you to define additional dependencies, it is the same as using the Dependencies: manifest attribute -->
+ <dependencies>
+ <module name="org.bouncycastle"/>
+ <module name="org.jboss.resteasy.resteasy-jaxrs" services="import"/>
+ <module name="org.jboss.resteasy.resteasy-crypto"/>
+ <module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/>
+ <module name="org.jboss.resteasy.jose-jwt" />
+ </dependencies>
+ </deployment>
+</jboss-deployment-structure>
\ No newline at end of file
testsuite/src/test/resources/persistence.xml 33(+33 -0)
diff --git a/testsuite/src/test/resources/persistence.xml b/testsuite/src/test/resources/persistence.xml
new file mode 100755
index 0000000..ad40046
--- /dev/null
+++ b/testsuite/src/test/resources/persistence.xml
@@ -0,0 +1,33 @@
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
+ version="1.0">
+ <persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
+ <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
+
+ <class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
+ <class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
+ <class>org.keycloak.services.models.picketlink.mappings.RealmEntity</class>
+ <class>org.keycloak.services.models.picketlink.mappings.ApplicationEntity</class>
+
+ <exclude-unlisted-classes>true</exclude-unlisted-classes>
+
+ <properties>
+ <property name="hibernate.hbm2ddl.auto" value="create-drop" />
+ <property name="hibernate.show_sql" value="false" />
+ <property name="hibernate.format_sql" value="false" />
+ </properties>
+ </persistence-unit>
+
+</persistence>
testsuite/src/test/resources/testrealm.json 76(+76 -0)
diff --git a/testsuite/src/test/resources/testrealm.json b/testsuite/src/test/resources/testrealm.json
new file mode 100755
index 0000000..cf42937
--- /dev/null
+++ b/testsuite/src/test/resources/testrealm.json
@@ -0,0 +1,76 @@
+{
+ "realm": "demo",
+ "enabled": true,
+ "tokenLifespan": 300,
+ "accessCodeLifespan": 10,
+ "sslNotRequired": true,
+ "cookieLoginAllowed": true,
+ "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" ],
+ "requiredApplicationCredentials": [ "password" ],
+ "requiredOAuthClientCredentials": [ "password" ],
+ "defaultRoles": [ "user" ],
+ "users" : [
+ {
+ "username" : "bburke@redhat.com",
+ "enabled" : true,
+ "attributes" : {
+ "email" : "bburke@redhat.com"
+ },
+ "credentials" : [
+ { "type" : "password",
+ "value" : "password" }
+ ]
+ },
+ {
+ "username" : "third-party",
+ "enabled" : true,
+ "credentials" : [
+ { "type" : "password",
+ "value" : "password" }
+ ]
+ }
+ ],
+ "roles": [
+ {
+ "name": "user",
+ "description": "Have User privileges"
+ },
+ {
+ "name": "admin",
+ "description": "Have Administrator privileges"
+ }
+ ],
+ "roleMappings": [
+ {
+ "username": "bburke@redhat.com",
+ "roles": ["user"]
+ },
+ {
+ "username": "third-party",
+ "roles": ["KEYCLOAK_IDENTITY_REQUESTER"]
+ }
+ ],
+ "scopeMappings": [
+ {
+ "username": "third-party",
+ "roles": ["user"]
+ }
+ ],
+ "applications": [
+ {
+ "name": "customer-portal",
+ "enabled": true,
+ "adminUrl": "http://localhost:8080/app/j_admin_request",
+ "useRealmMappings": true,
+ "credentials": [
+ {
+ "type": "password",
+ "value": "password"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
testsuite/src/test/resources/user.jsp 14(+14 -0)
diff --git a/testsuite/src/test/resources/user.jsp b/testsuite/src/test/resources/user.jsp
new file mode 100755
index 0000000..75afd76
--- /dev/null
+++ b/testsuite/src/test/resources/user.jsp
@@ -0,0 +1,14 @@
+<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
+<html>
+<head>
+<title>User</title>
+</head>
+<body>
+ <%
+ String user = request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : "not logged in";
+ String redirectUri = request.getRequestURL().toString();
+ %>
+ <a href="http://localhost:8080/auth-server/rest/realms/demo/tokens/logout?redirect_uri=<%=redirectUri%>" id="logout">logout</a>
+ <span id="user"><%=user%></span>
+</body>
+</html>
\ No newline at end of file
testsuite/src/test/resources/web.xml 39(+39 -0)
diff --git a/testsuite/src/test/resources/web.xml b/testsuite/src/test/resources/web.xml
new file mode 100755
index 0000000..76426e6
--- /dev/null
+++ b/testsuite/src/test/resources/web.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>auth-server</module-name>
+
+ <servlet>
+ <servlet-name>Resteasy</servlet-name>
+ <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.keycloak.testsuite.TestApplication</param-value>
+ </init-param>
+ <init-param>
+ <param-name>resteasy.servlet.mapping.prefix</param-name>
+ <param-value>/rest</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ <async-supported>true</async-supported>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Resteasy</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <!--
+ <security-constraint>
+ <web-resource-collection>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint> -->
+
+</web-app>