diff --git a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/AssertEventsServletFilter.java b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/AssertEventsServletFilter.java index 6d0d4ed198..1f4724d7a5 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/AssertEventsServletFilter.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/AssertEventsServletFilter.java @@ -44,6 +44,11 @@ public class AssertEventsServletFilter implements Filter { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; + if ("/clear-event-queue".equals(req.getRequestURI().substring(req.getContextPath().length()))) { + EventsListenerProvider.getInstance().clear(); + return; + } + if ("/event-queue".equals(req.getRequestURI().substring(req.getContextPath().length()))) { BlockingQueue events = EventsListenerProvider.getInstance(); HttpServletResponse resp = (HttpServletResponse) servletResponse; diff --git a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/EventsServer.java b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/EventsServer.java index 0b04ee3530..e18be4b912 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/EventsServer.java +++ b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/events/EventsServer.java @@ -69,6 +69,7 @@ public class EventsServer { FilterInfo filter = Servlets.filter("EventsFilter", AssertEventsServletFilter.class); di.addFilter(filter); di.addFilterUrlMapping("EventsFilter", "/event-queue", DispatcherType.REQUEST); + di.addFilterUrlMapping("EventsFilter", "/clear-event-queue", DispatcherType.REQUEST); DeploymentManager manager = container.addDeployment(di); manager.deploy(); diff --git a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java new file mode 100644 index 0000000000..52e5858db2 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProvider.java @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package org.keycloak.testsuite.rest; + +import org.keycloak.models.KeycloakSession; +import org.keycloak.services.resource.RealmResourceProvider; +import org.keycloak.services.resources.RealmsResource; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +/** + * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class TestApplicationResourceProvider implements RealmResourceProvider { + + private KeycloakSession session; + + public TestApplicationResourceProvider(KeycloakSession session) { + this.session = session; + } + + @GET + @Produces(MediaType.TEXT_HTML) + @Path("/{action}") + public String get(@PathParam("action") String action) { + //String requestUri = session.getContext().getUri().getRequestUri().toString(); + + String title = "APP_REQUEST"; + if (action.equals("auth")) { + title = "AUTH_RESPONSE"; + } else if (action.equals("logout")) { + title = "LOGOUT_REQUEST"; + } + + StringBuilder sb = new StringBuilder(); + sb.append("" + title + ""); + UriBuilder base = UriBuilder.fromUri("http://localhost:8180/auth"); + sb.append("account"); + + sb.append(""); + return sb.toString(); + } + + @Override + public Object getResource() { + return this; + } + + @Override + public void close() { + + } +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java new file mode 100644 index 0000000000..e795420b14 --- /dev/null +++ b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/java/org/keycloak/testsuite/rest/TestApplicationResourceProviderFactory.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package org.keycloak.testsuite.rest; + +import org.keycloak.Config.Scope; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.services.resource.RealmResourceProvider; +import org.keycloak.services.resource.RealmResourceProviderFactory; + +/** + * @author Stian Thorgersen + */ +public class TestApplicationResourceProviderFactory implements RealmResourceProviderFactory { + + @Override + public RealmResourceProvider create(KeycloakSession session) { + return new TestApplicationResourceProvider(session); + } + + @Override + public void init(Scope config) { + } + + @Override + public void postInit(KeycloakSessionFactory factory) { + } + + @Override + public void close() { + } + + @Override + public String getId() { + return "app"; + } + +} diff --git a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/resources/META-INF/services/org.keycloak.services.resource.RealmResourceProviderFactory b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/resources/META-INF/services/org.keycloak.services.resource.RealmResourceProviderFactory index 57d5390413..9a97746834 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/resources/META-INF/services/org.keycloak.services.resource.RealmResourceProviderFactory +++ b/testsuite/integration-arquillian/servers/auth-server/services/event-queue/src/main/resources/META-INF/services/org.keycloak.services.resource.RealmResourceProviderFactory @@ -15,4 +15,5 @@ # limitations under the License. # -org.keycloak.testsuite.rest.TimeOffsetResourceProviderFactory \ No newline at end of file +org.keycloak.testsuite.rest.TimeOffsetResourceProviderFactory +org.keycloak.testsuite.rest.TestApplicationResourceProviderFactory \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/provider/OAuthClientProvider.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/provider/OAuthClientProvider.java index b51a3bdd7f..ae07842694 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/provider/OAuthClientProvider.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/provider/OAuthClientProvider.java @@ -21,7 +21,7 @@ import org.jboss.arquillian.core.api.Instance; import org.jboss.arquillian.core.api.annotation.Inject; import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.arquillian.test.spi.enricher.resource.ResourceProvider; -import org.keycloak.testsuite.util.OAuthClient; +import org.keycloak.testsuite.util.DeleteMeOAuthClient; import java.lang.annotation.Annotation; @@ -31,11 +31,11 @@ import java.lang.annotation.Annotation; public class OAuthClientProvider implements ResourceProvider { @Inject - Instance oauthClient; + Instance oauthClient; @Override public boolean canProvide(Class type) { - return OAuthClient.class.isAssignableFrom(type); + return DeleteMeOAuthClient.class.isAssignableFrom(type); } @Override diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/DeleteMeOAuthClient.java similarity index 97% rename from testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java rename to testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/DeleteMeOAuthClient.java index efbcac7592..d834491ebc 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/DeleteMeOAuthClient.java @@ -40,11 +40,11 @@ import java.util.List; /** * @author Stian Thorgersen */ -public class OAuthClient { +public class DeleteMeOAuthClient { private String baseUrl; - public OAuthClient(String baseUrl) { + public DeleteMeOAuthClient(String baseUrl) { this.baseUrl = baseUrl; } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java index 3e42a58b4b..11cda101cd 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java @@ -60,19 +60,23 @@ import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; import org.keycloak.testsuite.arquillian.SuiteContext; import org.keycloak.testsuite.auth.page.WelcomePage; -import org.keycloak.testsuite.util.OAuthClient; +import org.keycloak.testsuite.util.DeleteMeOAuthClient; import org.keycloak.util.JsonSerialization; import org.openqa.selenium.WebDriver; import org.keycloak.testsuite.auth.page.AuthServer; import org.keycloak.testsuite.auth.page.AuthServerContextRoot; import org.keycloak.testsuite.auth.page.AuthRealm; + import static org.keycloak.testsuite.auth.page.AuthRealm.ADMIN; import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER; + import org.keycloak.testsuite.auth.page.account.Account; import org.keycloak.testsuite.auth.page.login.OIDCLogin; import org.keycloak.testsuite.auth.page.login.UpdatePassword; import org.keycloak.testsuite.util.WaitUtils; + import static org.keycloak.testsuite.admin.Users.setPasswordFor; + import org.keycloak.testsuite.util.TestEventsLogger; /** @@ -93,7 +97,7 @@ public abstract class AbstractKeycloakTest { protected Keycloak adminClient; - protected OAuthClient oauthClient; + protected DeleteMeOAuthClient oauthClient; protected List testRealmReps; @@ -128,7 +132,7 @@ public abstract class AbstractKeycloakTest { public void beforeAbstractKeycloakTest() { adminClient = Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth", MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID); - oauthClient = new OAuthClient(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth"); + oauthClient = new DeleteMeOAuthClient(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth"); adminUser = createAdminUserRepresentation(); @@ -155,7 +159,7 @@ public abstract class AbstractKeycloakTest { } // removeTestRealms(); // keeping test realms after test to be able to inspect failures, instead deleting existing realms before import -// keycloak.close(); // keeping admin connection open +// adminClient.close(); // keeping admin connection open } private void updateMasterAdminPassword() { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AssertEvents.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AssertEvents.java index 8e4c92ac85..f66fdf8ec1 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AssertEvents.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AssertEvents.java @@ -57,7 +57,7 @@ public class AssertEvents { static final String DEFAULT_REALM = "test"; static final String DEFAULT_USERNAME = "test-user@localhost"; - String defaultRedirectUri = "http://localhost:8081/app/auth"; + String defaultRedirectUri = "http://localhost:8180/auth/realms/master/app/auth"; String defaultEventsQueueUri = "http://localhost:8092"; private RealmResource realmResource; @@ -96,7 +96,23 @@ public class AssertEvents { } public void clear() { - realmResource.clearEvents(); + CloseableHttpClient httpclient = HttpClients.createDefault(); + try { + HttpPost post = new HttpPost(defaultEventsQueueUri + "/clear-event-queue"); + CloseableHttpResponse response = httpclient.execute(post); + if (response.getStatusLine().getStatusCode() != 200) { + throw new RuntimeException("Failed to clear events from " + post.getURI() + ": " + response.getStatusLine().toString()); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + finally { + try { + httpclient.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } } public ExpectedEvent expectRequiredAction(EventType event) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java new file mode 100644 index 0000000000..00a2cf96b9 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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. + */ + +package org.keycloak.testsuite; + +import org.keycloak.testsuite.util.OAuthClient; +import java.util.List; +import org.junit.Before; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson; + +/** + * This class provides loading of the testRealm called "test". It also + * provides an OAuthClient for the testRealm. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public abstract class TestRealmKeycloakTest extends AbstractKeycloakTest { + + protected OAuthClient oauth; + + protected ClientRepresentation findTestApp(RealmRepresentation testRealm) { + for (ClientRepresentation client : testRealm.getClients()) { + if (client.getClientId().equals("test-app")) return client; + } + + return null; + } + + @Override + public void addTestRealms(List testRealms) { + RealmRepresentation testRealm = loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class); + + oauth = new OAuthClient(driver, testRealm.getPublicKey()); + + testRealms.add(testRealm); + + configureTestRealm(testRealm); + } + + /** + * This allows a subclass to change the configuration of the testRealm before + * it is imported. This method will be called prior to any @Before methods + * in the subclass. + * + * @param testRealm The realm read from /testrealm.json. + */ + public abstract void configureTestRealm(RealmRepresentation testRealm); + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AbstractAdminTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AbstractAdminTest.java new file mode 100644 index 0000000000..b02c21f8fd --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/AbstractAdminTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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. + */ + +package org.keycloak.testsuite.admin; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.After; +import org.junit.Before; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.util.JsonSerialization; + +import static org.junit.Assert.assertArrayEquals; + +/** + * This class adapts the functionality from the old testsuite to make tests + * easier to port. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public abstract class AbstractAdminTest extends TestRealmKeycloakTest { + protected static final String REALM_NAME = "admin-client-test"; + + protected RealmResource realm; + + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + findTestApp(testRealm).setDirectAccessGrantsEnabled(true); + } + + @Override + public void addTestRealms(List testRealms) { + super.addTestRealms(testRealms); + + RealmRepresentation adminRealmRep = new RealmRepresentation(); + adminRealmRep.setRealm(REALM_NAME); + adminRealmRep.setEnabled(true); + Map config = new HashMap<>(); + config.put("from", "auto@keycloak.org"); + config.put("host", "localhost"); + config.put("port", "3025"); + adminRealmRep.setSmtpServer(config); + testRealms.add(adminRealmRep); + } + + @Before + public void setRealm() { + realm = adminClient.realm(REALM_NAME); + } + + // old testsuite expects this realm to be removed at the end of the test + // not sure if it really matters + @After + public void after() { + for (RealmRepresentation r : adminClient.realms().findAll()) { + if (r.getRealm().equals(REALM_NAME)) { + removeRealm(r); + } + } + } + + // Taken from Keycloak class in old testsuite. + // So, code in old testsuite calling this looks like Keycloak.loadJson(.....) + public static T loadJson(InputStream is, Class type) { + try { + return JsonSerialization.readValue(is, type); + } catch (IOException e) { + throw new RuntimeException("Failed to parse json", e); + } + } + + public static void assertNames(List actual, String... expected) { + Arrays.sort(expected); + String[] actualNames = names(actual); + assertArrayEquals("Expected: " + Arrays.toString(expected) + ", was: " + Arrays.toString(actualNames), expected, actualNames); + } + + public static List sort(List list) { + Collections.sort(list, new Comparator() { + @Override + public int compare(Object o1, Object o2) { + return name(o1).compareTo(name(o2)); + } + }); + return list; + } + + public static String[] names(List list) { + String[] names = new String[list.size()]; + for (int i = 0; i < list.size(); i++) { + names[i] = name(list.get(i)); + } + Arrays.sort(names); + return names; + } + + public static String name(Object o1) { + if (o1 instanceof RealmRepresentation) { + return ((RealmRepresentation) o1).getRealm(); + } else if (o1 instanceof ClientRepresentation) { + return ((ClientRepresentation) o1).getClientId(); + } else if (o1 instanceof IdentityProviderRepresentation) { + return ((IdentityProviderRepresentation) o1).getAlias(); + } + throw new IllegalArgumentException(); + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java new file mode 100644 index 0000000000..0f8ee1f2ae --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ApiUtil.java @@ -0,0 +1,157 @@ +/* + * 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. + */ +package org.keycloak.testsuite.admin; + +import org.jboss.logging.Logger; +import org.keycloak.admin.client.resource.ClientResource; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.RoleRepresentation; +import org.keycloak.representations.idm.UserRepresentation; + +import javax.ws.rs.core.Response; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.Response.StatusType; + +import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD; + +import org.keycloak.representations.idm.GroupRepresentation; + +/** + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class ApiUtil { + + private static final Logger log = Logger.getLogger(ApiUtil.class); + + public static String getCreatedId(Response response) { + URI location = response.getLocation(); + if (!response.getStatusInfo().equals(Status.CREATED)) { + StatusType statusInfo = response.getStatusInfo(); + throw new RuntimeException("Create method returned status " + + statusInfo.getReasonPhrase() + " (Code: " + statusInfo.getStatusCode() + "); expected status: Created (201)"); + } + if (location == null) { + return null; + } + String path = location.getPath(); + return path.substring(path.lastIndexOf('/') + 1); + } + + public static ClientResource findClientResourceByClientId(RealmResource realm, String clientId) { + for (ClientRepresentation c : realm.clients().findAll()) { + if (c.getClientId().equals(clientId)) { + return realm.clients().get(c.getId()); + } + } + return null; + } + + public static ClientResource findClientResourceByName(RealmResource realm, String name) { + for (ClientRepresentation c : realm.clients().findAll()) { + if (c.getName().equals(name)) { + return realm.clients().get(c.getId()); + } + } + return null; + } + + public static ClientResource findClientByClientId(RealmResource realm, String clientId) { + for (ClientRepresentation c : realm.clients().findAll()) { + if (c.getClientId().equals(clientId)) { + return realm.clients().get(c.getId()); + } + } + return null; + } + + public static UserRepresentation findUserByUsername(RealmResource realm, String username) { + UserRepresentation user = null; + List ur = realm.users().search(username, null, null); + if (ur.size() == 1) { + user = ur.get(0); + } + return user; + } + + public static String createUserWithAdminClient(RealmResource realm, UserRepresentation user) { + Response response = realm.users().create(user); + String createdId = getCreatedId(response); + response.close(); + return createdId; + } + + public static String createUserAndResetPasswordWithAdminClient(RealmResource realm, UserRepresentation user, String password) { + String id = createUserWithAdminClient(realm, user); + resetUserPassword(realm.users().get(id), password, false); + return id; + } + + public static void resetUserPassword(UserResource userResource, String newPassword, boolean temporary) { + CredentialRepresentation newCredential = new CredentialRepresentation(); + newCredential.setType(PASSWORD); + newCredential.setValue(newPassword); + newCredential.setTemporary(temporary); + userResource.resetPassword(newCredential); + } + + public static void assignClientRoles(RealmResource realm, String userId, String clientName, String... roles) { + String realmName = realm.toRepresentation().getRealm(); + String clientId = ""; + for (ClientRepresentation clientRepresentation : realm.clients().findAll()) { + if (clientRepresentation.getClientId().equals(clientName)) { + clientId = clientRepresentation.getId(); + } + } + + if (!clientId.isEmpty()) { + ClientResource clientResource = realm.clients().get(clientId); + + List roleRepresentations = new ArrayList<>(); + for (String roleName : roles) { + RoleRepresentation role = clientResource.roles().get(roleName).toRepresentation(); + roleRepresentations.add(role); + } + + UserResource userResource = realm.users().get(userId); + log.debug("assigning roles: " + Arrays.toString(roles) + " to user: \"" + + userResource.toRepresentation().getUsername() + "\" of client: \"" + + clientName + "\" in realm: \"" + realmName + "\""); + userResource.roles().clientLevel(clientId).add(roleRepresentations); + } else { + log.warn("client with name " + clientName + "doesn't exist in realm " + realmName); + } + } + + public static boolean groupContainsSubgroup(GroupRepresentation group, GroupRepresentation subgroup) { + boolean contains = false; + for (GroupRepresentation sg : group.getSubGroups()) { + if (subgroup.getId().equals(sg.getId())) { + contains = true; + break; + } + } + return contains; + } + +} diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java old mode 100755 new mode 100644 similarity index 95% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java index 76ef0e6e25..ac626e0d99 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/ClientTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java @@ -18,17 +18,12 @@ package org.keycloak.testsuite.admin; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ProtocolMappersResource; import org.keycloak.models.Constants; import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory; import org.keycloak.representations.idm.*; -import org.keycloak.testsuite.OAuthClient; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; -import org.openqa.selenium.WebDriver; import javax.ws.rs.NotFoundException; import javax.ws.rs.core.Response; @@ -36,6 +31,7 @@ import javax.ws.rs.core.Response; import java.util.HashSet; import java.util.List; import java.util.Set; +import org.keycloak.testsuite.util.OAuthClient; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -47,16 +43,7 @@ import static org.junit.Assert.fail; /** * @author Stian Thorgersen */ -public class ClientTest extends AbstractClientTest { - - @Rule - public WebRule webRule = new WebRule(this); - - @WebResource - protected WebDriver driver; - - @WebResource - protected OAuthClient oauth; +public class ClientTest extends AbstractAdminTest { @Test public void getClients() { @@ -122,7 +109,7 @@ public class ClientTest extends AbstractClientTest { OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(codeResponse.getCode(), "password"); assertEquals(200, response2.getStatusCode()); - ClientResource app = ApiUtil.findClientByClientId(keycloak.realm("test"), "test-app"); + ClientResource app = ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app"); assertEquals(2, (long) app.getApplicationSessionCount().get("count")); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/AbstractAuthenticationTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/AbstractAuthenticationTest.java index fb7e966156..cbb37cfc91 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/AbstractAuthenticationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/AbstractAuthenticationTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Before; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ExecutionTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ExecutionTest.java index afe702f033..02afffaf47 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ExecutionTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/FlowTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/FlowTest.java index d381beca67..cd7d00631c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/FlowTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/FlowTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/InitialFlowsTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/InitialFlowsTest.java index 45f538fbd3..d66cb29683 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/InitialFlowsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/InitialFlowsTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ProvidersTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ProvidersTest.java index 9f679e35c2..0abb5c8cbe 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ProvidersTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ProvidersTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/RequiredActionsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/RequiredActionsTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/RequiredActionsTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/RequiredActionsTest.java index 0ac68649e4..a73501c633 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/RequiredActionsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/RequiredActionsTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ShiftExecutionTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ShiftExecutionTest.java index b7c3c15c61..107e7c320d 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ShiftExecutionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/authentication/ShiftExecutionTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.authentication; +package org.keycloak.testsuite.endpoint.authentication; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/AbstractClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/AbstractClientTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/AbstractClientTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/AbstractClientTest.java index 9913c1764c..ba0901e546 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/AbstractClientTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/AbstractClientTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import java.util.List; import javax.ws.rs.core.Response; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientProtocolMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientProtocolMapperTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientProtocolMapperTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientProtocolMapperTest.java index acf2329fba..f7db1e28e8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientProtocolMapperTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientProtocolMapperTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import java.util.ArrayList; import java.util.HashMap; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientRolesTest.java similarity index 97% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientRolesTest.java index 5fb7c7dd0b..fec32a2a73 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientRolesTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientRolesTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import org.junit.After; import org.junit.Before; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java index 1eebf390bc..8fd43fd23c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTemplateTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTemplateTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import java.util.Collections; import java.util.List; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTest.java index 1670a6b80b..a1aec62b23 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/ClientTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/ClientTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import java.util.List; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/CredentialsTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/CredentialsTest.java index 2b79e50af9..3262d44649 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/CredentialsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/CredentialsTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import org.junit.Before; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/InstallationTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/InstallationTest.java index 71371988aa..fcc78dc19c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/InstallationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/InstallationTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import org.junit.After; import org.junit.Before; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/SessionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/SessionTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/SessionTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/SessionTest.java index cf15f960a9..406ff68bcc 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/SessionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/client/SessionTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.client; +package org.keycloak.testsuite.endpoint.client; import java.util.List; import org.jboss.arquillian.graphene.page.Page; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/AbstractEventTest.java similarity index 97% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/AbstractEventTest.java index 597556cea5..9b47c15b1a 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AbstractEventTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/AbstractEventTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.event; +package org.keycloak.testsuite.endpoint.event; import java.util.Collections; import org.junit.Before; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/AdminEventTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/AdminEventTest.java index d7c0845626..e011925559 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/AdminEventTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.event; +package org.keycloak.testsuite.endpoint.event; import java.util.Arrays; import java.util.Collections; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/EventConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/EventConfigTest.java similarity index 98% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/EventConfigTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/EventConfigTest.java index 53a07ccf34..c908f1d59b 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/EventConfigTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/EventConfigTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.event; +package org.keycloak.testsuite.endpoint.event; import java.util.Arrays; import java.util.Collections; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/LoginEventsTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/LoginEventsTest.java index fa44674e3c..f3f3dd61a4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/event/LoginEventsTest.java @@ -15,7 +15,7 @@ * the License. */ -package org.keycloak.testsuite.admin.event; +package org.keycloak.testsuite.endpoint.event; import java.util.Arrays; import java.util.List; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/AbstractGroupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/AbstractGroupTest.java similarity index 97% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/AbstractGroupTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/AbstractGroupTest.java index 264551b531..0636872276 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/AbstractGroupTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/AbstractGroupTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.group; +package org.keycloak.testsuite.endpoint.group; import org.junit.Before; import org.keycloak.OAuth2Constants; @@ -45,6 +45,7 @@ public abstract class AbstractGroupTest extends AbstractKeycloakTest { @Before public void initAssertEvents() throws Exception { events = new AssertEvents(this); + events.clear(); } AccessToken login(String login, String clientId, String clientSecret, String userId) throws Exception { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/GroupMappersTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/GroupMappersTest.java index d61a517ce6..78ef8451c4 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/GroupMappersTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.group; +package org.keycloak.testsuite.endpoint.group; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/GroupTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/GroupTest.java index adba8de095..b748197a31 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/group/GroupTest.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.keycloak.testsuite.admin.group; +package org.keycloak.testsuite.endpoint.group; import org.junit.Assert; import org.junit.Test; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/partialimport/PartialImportTest.java similarity index 99% rename from testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/partialimport/PartialImportTest.java index 1d746c3c0a..7815cb4daf 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/endpoint/partialimport/PartialImportTest.java @@ -14,7 +14,7 @@ * License for the specific language governing permissions and limitations under * the License. */ -package org.keycloak.testsuite.admin.partialimport; +package org.keycloak.testsuite.endpoint.partialimport; import java.util.ArrayList; import java.util.Arrays; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/LegacyImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/LegacyImportTest.java index 7fbbc95a4d..b0b4c12443 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/LegacyImportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/LegacyImportTest.java @@ -41,7 +41,7 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; /** - * Test importing JSON files exported from previous keycloak versions + * Test importing JSON files exported from previous adminClient versions * * @author Marek Posolda */ diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java similarity index 81% rename from testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java index 88a92476ed..54f218e890 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/TokenIntrospectionTest.java @@ -18,49 +18,47 @@ package org.keycloak.testsuite.oauth; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.ClassRule; -import org.junit.Rule; +import java.util.ArrayList; +import java.util.List; +import org.junit.Before; import org.junit.Test; import org.keycloak.OAuth2Constants; -import org.keycloak.admin.client.Keycloak; import org.keycloak.common.util.Time; -import org.keycloak.events.Event; -import org.keycloak.models.ClientModel; -import org.keycloak.models.Constants; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RoleModel; -import org.keycloak.models.UserCredentialModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.utils.KeycloakModelUtils; +import org.keycloak.testsuite.util.KeycloakModelUtils; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.EventRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.oidc.TokenMetadataRepresentation; -import org.keycloak.services.managers.ClientManager; -import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.AssertEvents; -import org.keycloak.testsuite.OAuthClient; -import org.keycloak.testsuite.OAuthClient.AccessTokenResponse; -import org.keycloak.testsuite.pages.LoginPage; -import org.keycloak.testsuite.rule.KeycloakRule; -import org.keycloak.testsuite.rule.WebResource; -import org.keycloak.testsuite.rule.WebRule; +import org.keycloak.testsuite.TestRealmKeycloakTest; +import org.keycloak.testsuite.util.OAuthClient.AccessTokenResponse; +//import org.adminClient.testsuite.pages.LoginPage; +//import org.adminClient.testsuite.rule.KeycloakRule; +//import org.adminClient.testsuite.rule.WebResource; +//import org.adminClient.testsuite.rule.WebRule; import org.keycloak.util.JsonSerialization; -import org.openqa.selenium.WebDriver; import static org.junit.Assert.*; /** * @author Pedro Igor + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. */ -public class TokenIntrospectionTest { +public class TokenIntrospectionTest extends TestRealmKeycloakTest { - protected static Keycloak keycloak; - - @ClassRule + private AssertEvents events; + + /* @ClassRule >>> now implemented in configureTestRealm() public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() { @Override + vvv "test" realm public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) { + vvv Done in TestRealmKeycloakTest vvv appRealm.getClientByClientId("test-app").setDirectAccessGrantsEnabled(true); + ClientModel confApp = KeycloakModelUtils.createClient(appRealm, "confidential-cli"); confApp.setSecret("secret1"); new ClientManager(manager).enableServiceAccount(confApp); @@ -74,25 +72,39 @@ public class TokenIntrospectionTest { user.grantRole(role); } - keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID); + adminClient = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID); } - }); + }); */ - @Rule - public WebRule webRule = new WebRule(this); + @Override + public void configureTestRealm(RealmRepresentation testRealm) { + ClientRepresentation confApp = KeycloakModelUtils.createClient(testRealm, "confidential-cli"); + confApp.setSecret("secret1"); + confApp.setServiceAccountsEnabled(Boolean.TRUE); - @WebResource - protected WebDriver driver; + ClientRepresentation pubApp = KeycloakModelUtils.createClient(testRealm, "public-cli"); + pubApp.setPublicClient(Boolean.TRUE); - @WebResource - protected OAuthClient oauth; + UserRepresentation user = new UserRepresentation(); + user.setUsername("no-permissions"); + CredentialRepresentation credential = new CredentialRepresentation(); + credential.setType("password"); + credential.setValue("password"); + List creds = new ArrayList<>(); + creds.add(credential); + user.setCredentials(creds); + user.setEnabled(Boolean.TRUE); + List realmRoles = new ArrayList<>(); + realmRoles.add("user"); + user.setRealmRoles(realmRoles); + testRealm.getUsers().add(user); + } - @WebResource - protected LoginPage loginPage; - - @Rule - public AssertEvents events = new AssertEvents(keycloakRule); + @Before + public void setUpAssertEvents() throws Exception { + events = new AssertEvents(this); + } @Test public void testConfidentialClientCredentialsBasicAuthentication() throws Exception { @@ -146,7 +158,7 @@ public class TokenIntrospectionTest { public void testIntrospectRefreshToken() throws Exception { oauth.doLogin("test-user@localhost", "password"); String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - Event loginEvent = events.expectLogin().assertEvent(); + EventRepresentation loginEvent = events.expectLogin().assertEvent(); String sessionId = loginEvent.getSessionId(); AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(code, "password"); String tokenResponse = oauth.introspectAccessTokenWithClientCredential("confidential-cli", "secret1", accessTokenResponse.getAccessToken()); @@ -215,7 +227,7 @@ public class TokenIntrospectionTest { public void testIntrospectAccessToken() throws Exception { oauth.doLogin("test-user@localhost", "password"); String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); - Event loginEvent = events.expectLogin().assertEvent(); + EventRepresentation loginEvent = events.expectLogin().assertEvent(); AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(code, "password"); String tokenResponse = oauth.introspectAccessTokenWithClientCredential("confidential-cli", "secret1", accessTokenResponse.getAccessToken()); TokenMetadataRepresentation rep = JsonSerialization.readValue(tokenResponse, TokenMetadataRepresentation.class); @@ -252,12 +264,12 @@ public class TokenIntrospectionTest { String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE); AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(code, "password"); - Event loginEvent = events.expectLogin().assertEvent(); + EventRepresentation loginEvent = events.expectLogin().assertEvent(); UserRepresentation userRep = new UserRepresentation(); try { userRep.setEnabled(false); - keycloak.realm(oauth.getRealm()).users().get(loginEvent.getUserId()).update(userRep); + adminClient.realm(oauth.getRealm()).users().get(loginEvent.getUserId()).update(userRep); String tokenResponse = oauth.introspectAccessTokenWithClientCredential("confidential-cli", "secret1", accessTokenResponse.getAccessToken()); TokenMetadataRepresentation rep = JsonSerialization.readValue(tokenResponse, TokenMetadataRepresentation.class); @@ -270,7 +282,7 @@ public class TokenIntrospectionTest { events.clear(); } finally { userRep.setEnabled(true); - keycloak.realm(oauth.getRealm()).users().get(loginEvent.getUserId()).update(userRep); + adminClient.realm(oauth.getRealm()).users().get(loginEvent.getUserId()).update(userRep); } } @@ -281,7 +293,7 @@ public class TokenIntrospectionTest { AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(code, "password"); try { - Time.setOffset(keycloak.realm(oauth.getRealm()).toRepresentation().getAccessTokenLifespan() + 1); + Time.setOffset(adminClient.realm(oauth.getRealm()).toRepresentation().getAccessTokenLifespan() + 1); String tokenResponse = oauth.introspectAccessTokenWithClientCredential("confidential-cli", "secret1", accessTokenResponse.getAccessToken()); TokenMetadataRepresentation rep = JsonSerialization.readValue(tokenResponse, TokenMetadataRepresentation.class); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/KeycloakModelUtils.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/KeycloakModelUtils.java new file mode 100644 index 0000000000..eda966d21e --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/KeycloakModelUtils.java @@ -0,0 +1,53 @@ +/* + * Copyright 2016 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * 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. + */ + +package org.keycloak.testsuite.util; + +import org.keycloak.models.UserCredentialModel; +import org.keycloak.models.utils.ModelToRepresentation; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; + +import static org.keycloak.models.utils.KeycloakModelUtils.getDefaultClientAuthenticatorType; + +/** + * This is a client-side version of KeycloakModelUtils that uses the adminClient to + * manipulate the model. + * + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class KeycloakModelUtils { + + public static ClientRepresentation createClient(RealmRepresentation realm, String name) { + ClientRepresentation app = new ClientRepresentation(); + app.setName(name); + app.setClientId(name); + realm.getClients().add(app); + app.setClientAuthenticatorType(getDefaultClientAuthenticatorType()); + generateSecret(app); + app.setFullScopeAllowed(true); + + return app; + } + + public static CredentialRepresentation generateSecret(ClientRepresentation client) { + UserCredentialModel secret = UserCredentialModel.generateSecret(); + client.setSecret(secret.getValue()); + return ModelToRepresentation.toRepresentation(secret); + } +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/OAuthClient.java new file mode 100644 index 0000000000..b213daec04 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/OAuthClient.java @@ -0,0 +1,645 @@ +/* + * 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. + */ +package org.keycloak.testsuite.util; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.junit.Assert; +import org.keycloak.OAuth2Constants; +import org.keycloak.RSATokenVerifier; +import org.keycloak.common.VerificationException; +import org.keycloak.common.util.PemUtils; +import org.keycloak.constants.AdapterConstants; +import org.keycloak.jose.jws.JWSInput; +import org.keycloak.jose.jws.crypto.RSAProvider; +import org.keycloak.protocol.oidc.OIDCLoginProtocolService; +import org.keycloak.representations.AccessToken; +import org.keycloak.representations.RefreshToken; +import org.keycloak.testsuite.arquillian.AuthServerTestEnricher; +import org.keycloak.util.BasicAuthHelper; +import org.keycloak.util.JsonSerialization; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; + +import javax.ws.rs.core.UriBuilder; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.PublicKey; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * @author Stian Thorgersen + * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. + */ +public class OAuthClient { + public static final String SERVER_ROOT = AuthServerTestEnricher.getAuthServerContextRoot(); + public static final String AUTH_SERVER_ROOT = SERVER_ROOT + "/auth"; + public static final String APP_ROOT = AUTH_SERVER_ROOT + "/realms/master/app"; + + private WebDriver driver; + + private String baseUrl = AUTH_SERVER_ROOT; + + private String realm = "test"; + + private String clientId = "test-app"; + + private String redirectUri = APP_ROOT + "/auth"; + + private String state = "mystate"; + + private String scope; + + private String uiLocales = null; + + private PublicKey realmPublicKey; + + private String clientSessionState; + + private String clientSessionHost; + + public OAuthClient(WebDriver driver, String publicKey) { + this.driver = driver; + + try { + realmPublicKey = PemUtils.decodePublicKey(publicKey); + } catch (Exception e) { + throw new RuntimeException("Failed to retrieve realm public key", e); + } + } + + public AuthorizationCodeResponse doLogin(String username, String password) { + openLoginForm(); + String src = driver.getPageSource(); + driver.findElement(By.id("username")).sendKeys(username); + driver.findElement(By.id("password")).sendKeys(password); + driver.findElement(By.name("login")).click(); + + return new AuthorizationCodeResponse(this); + } + + public void doLoginGrant(String username, String password) { + openLoginForm(); + + driver.findElement(By.id("username")).sendKeys(username); + driver.findElement(By.id("password")).sendKeys(password); + driver.findElement(By.name("login")).click(); + } + + public AccessTokenResponse doAccessTokenRequest(String code, String password) { + CloseableHttpClient client = new DefaultHttpClient(); + try { + HttpPost post = new HttpPost(getAccessTokenUrl()); + + List parameters = new LinkedList(); + parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.AUTHORIZATION_CODE)); + + if (code != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.CODE, code)); + } + if (redirectUri != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.REDIRECT_URI, redirectUri)); + } + if (clientId != null && password != null) { + String authorization = BasicAuthHelper.createHeader(clientId, password); + post.setHeader("Authorization", authorization); + } else if (clientId != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, clientId)); + } + + if (clientSessionState != null) { + parameters.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, clientSessionState)); + } + + if (clientSessionHost != null) { + parameters.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, clientSessionHost)); + } + + UrlEncodedFormEntity formEntity = null; + try { + formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + post.setEntity(formEntity); + + try { + return new AccessTokenResponse(client.execute(post)); + } catch (Exception e) { + throw new RuntimeException("Failed to retrieve access token", e); + } + } finally { + closeClient(client); + } + } + + public String introspectAccessTokenWithClientCredential(String clientId, String clientSecret, String tokenToIntrospect) { + return introspectTokenWithClientCredential(clientId, clientSecret, "access_token", tokenToIntrospect); + } + + public String introspectRefreshTokenWithClientCredential(String clientId, String clientSecret, String tokenToIntrospect) { + return introspectTokenWithClientCredential(clientId, clientSecret, "refresh_token", tokenToIntrospect); + } + + public String introspectTokenWithClientCredential(String clientId, String clientSecret, String tokenType, String tokenToIntrospect) { + CloseableHttpClient client = new DefaultHttpClient(); + try { + HttpPost post = new HttpPost(getTokenIntrospectionUrl()); + + String authorization = BasicAuthHelper.createHeader(clientId, clientSecret); + post.setHeader("Authorization", authorization); + + List parameters = new LinkedList<>(); + + parameters.add(new BasicNameValuePair("token", tokenToIntrospect)); + parameters.add(new BasicNameValuePair("token_type_hint", tokenType)); + + UrlEncodedFormEntity formEntity; + + try { + formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + post.setEntity(formEntity); + + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + client.execute(post).getEntity().writeTo(out); + + return new String(out.toByteArray()); + } catch (Exception e) { + throw new RuntimeException("Failed to retrieve access token", e); + } + } finally { + closeClient(client); + } + } + + public AccessTokenResponse doGrantAccessTokenRequest(String clientSecret, String username, String password) throws Exception { + return doGrantAccessTokenRequest(realm, username, password, null, clientId, clientSecret); + } + + public AccessTokenResponse doGrantAccessTokenRequest(String clientSecret, String username, String password, String otp) throws Exception { + return doGrantAccessTokenRequest(realm, username, password, otp, clientId, clientSecret); + } + + public AccessTokenResponse doGrantAccessTokenRequest(String realm, String username, String password, String totp, + String clientId, String clientSecret) throws Exception { + CloseableHttpClient client = new DefaultHttpClient(); + try { + HttpPost post = new HttpPost(getResourceOwnerPasswordCredentialGrantUrl(realm)); + + List parameters = new LinkedList(); + parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD)); + parameters.add(new BasicNameValuePair("username", username)); + parameters.add(new BasicNameValuePair("password", password)); + if (totp != null) { + parameters.add(new BasicNameValuePair("totp", totp)); + + } + if (clientSecret != null) { + String authorization = BasicAuthHelper.createHeader(clientId, clientSecret); + post.setHeader("Authorization", authorization); + } else { + parameters.add(new BasicNameValuePair("client_id", clientId)); + + } + + if (clientSessionState != null) { + parameters.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, clientSessionState)); + } + if (clientSessionHost != null) { + parameters.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, clientSessionHost)); + } + if (scope != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.SCOPE, scope)); + } + + UrlEncodedFormEntity formEntity; + try { + formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + post.setEntity(formEntity); + + return new AccessTokenResponse(client.execute(post)); + } finally { + closeClient(client); + } + } + + public AccessTokenResponse doClientCredentialsGrantAccessTokenRequest(String clientSecret) throws Exception { + CloseableHttpClient client = new DefaultHttpClient(); + try { + HttpPost post = new HttpPost(getServiceAccountUrl()); + + String authorization = BasicAuthHelper.createHeader(clientId, clientSecret); + post.setHeader("Authorization", authorization); + + List parameters = new LinkedList(); + parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.CLIENT_CREDENTIALS)); + + if (scope != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.SCOPE, scope)); + } + + UrlEncodedFormEntity formEntity; + try { + formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + post.setEntity(formEntity); + + return new AccessTokenResponse(client.execute(post)); + } finally { + closeClient(client); + } + } + + + public HttpResponse doLogout(String refreshToken, String clientSecret) throws IOException { + CloseableHttpClient client = new DefaultHttpClient(); + try { + HttpPost post = new HttpPost(getLogoutUrl(null, null)); + + List parameters = new LinkedList(); + if (refreshToken != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, refreshToken)); + } + if (clientId != null && clientSecret != null) { + String authorization = BasicAuthHelper.createHeader(clientId, clientSecret); + post.setHeader("Authorization", authorization); + } else if (clientId != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, clientId)); + } + + UrlEncodedFormEntity formEntity; + try { + formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + post.setEntity(formEntity); + + return client.execute(post); + } finally { + closeClient(client); + } + } + + public AccessTokenResponse doRefreshTokenRequest(String refreshToken, String password) { + CloseableHttpClient client = new DefaultHttpClient(); + try { + HttpPost post = new HttpPost(getRefreshTokenUrl()); + + List parameters = new LinkedList(); + parameters.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, OAuth2Constants.REFRESH_TOKEN)); + + if (refreshToken != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, refreshToken)); + } + if (clientId != null && password != null) { + String authorization = BasicAuthHelper.createHeader(clientId, password); + post.setHeader("Authorization", authorization); + } else if (clientId != null) { + parameters.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, clientId)); + } + + if (clientSessionState != null) { + parameters.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_STATE, clientSessionState)); + } + if (clientSessionHost != null) { + parameters.add(new BasicNameValuePair(AdapterConstants.CLIENT_SESSION_HOST, clientSessionHost)); + } + + UrlEncodedFormEntity formEntity; + try { + formEntity = new UrlEncodedFormEntity(parameters, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + post.setEntity(formEntity); + + try { + return new AccessTokenResponse(client.execute(post)); + } catch (Exception e) { + throw new RuntimeException("Failed to retrieve access token", e); + } + } finally { + closeClient(client); + } + } + + public void closeClient(CloseableHttpClient client) { + try { + client.close(); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + + public AccessToken verifyToken(String token) { + try { + return RSATokenVerifier.verifyToken(token, realmPublicKey, baseUrl + "/realms/" + realm); + } catch (VerificationException e) { + throw new RuntimeException("Failed to verify token", e); + } + } + + public RefreshToken verifyRefreshToken(String refreshToken) { + try { + JWSInput jws = new JWSInput(refreshToken); + if (!RSAProvider.verify(jws, realmPublicKey)) { + throw new RuntimeException("Invalid refresh token"); + } + return jws.readJsonContent(RefreshToken.class); + } catch (Exception e) { + throw new RuntimeException("Invalid refresh token", e); + } + } + + public String getClientId() { + return clientId; + } + + public String getCurrentRequest() { + return driver.getCurrentUrl().substring(0, driver.getCurrentUrl().indexOf('?')); + } + + public URI getCurrentUri() { + try { + return new URI(driver.getCurrentUrl()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + public Map getCurrentQuery() { + Map m = new HashMap(); + List pairs = URLEncodedUtils.parse(getCurrentUri(), "UTF-8"); + for (NameValuePair p : pairs) { + m.put(p.getName(), p.getValue()); + } + return m; + } + + public void openLoginForm() { + driver.navigate().to(getLoginFormUrl()); + } + + public void openLogout() { + UriBuilder b = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(baseUrl)); + if (redirectUri != null) { + b.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri); + } + driver.navigate().to(b.build(realm).toString()); + } + + public String getRedirectUri() { + return redirectUri; + } + + public String getLoginFormUrl() { + UriBuilder b = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(SERVER_ROOT + "/auth")); + b.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE); + if (clientId != null) { + b.queryParam(OAuth2Constants.CLIENT_ID, clientId); + } + if (redirectUri != null) { + b.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri); + } + if (state != null) { + b.queryParam(OAuth2Constants.STATE, state); + } + if(uiLocales != null){ + b.queryParam(OAuth2Constants.UI_LOCALES_PARAM, uiLocales); + } + if (scope != null) { + b.queryParam(OAuth2Constants.SCOPE, scope); + } + return b.build(realm).toString(); + } + + public String getAccessTokenUrl() { + UriBuilder b = OIDCLoginProtocolService.tokenUrl(UriBuilder.fromUri(baseUrl)); + return b.build(realm).toString(); + } + + public String getTokenIntrospectionUrl() { + UriBuilder b = OIDCLoginProtocolService.tokenIntrospectionUrl(UriBuilder.fromUri(baseUrl)); + return b.build(realm).toString(); + } + + public String getLogoutUrl(String redirectUri, String sessionState) { + UriBuilder b = OIDCLoginProtocolService.logoutUrl(UriBuilder.fromUri(baseUrl)); + if (redirectUri != null) { + b.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri); + } + if (sessionState != null) { + b.queryParam("session_state", sessionState); + } + return b.build(realm).toString(); + } + + public String getResourceOwnerPasswordCredentialGrantUrl() { + UriBuilder b = OIDCLoginProtocolService.tokenUrl(UriBuilder.fromUri(baseUrl)); + return b.build(realm).toString(); + } + + public String getResourceOwnerPasswordCredentialGrantUrl(String realm) { + UriBuilder b = OIDCLoginProtocolService.tokenUrl(UriBuilder.fromUri(baseUrl)); + return b.build(realm).toString(); + } + + public String getServiceAccountUrl() { + return getResourceOwnerPasswordCredentialGrantUrl(); + } + + public String getRefreshTokenUrl() { + UriBuilder b = OIDCLoginProtocolService.tokenUrl(UriBuilder.fromUri(baseUrl)); + return b.build(realm).toString(); + } + + public OAuthClient realm(String realm) { + this.realm = realm; + return this; + } + public OAuthClient realmPublicKey(PublicKey key) { + this.realmPublicKey = key; + return this; + } + + public OAuthClient clientId(String clientId) { + this.clientId = clientId; + return this; + } + + public OAuthClient redirectUri(String redirectUri) { + this.redirectUri = redirectUri; + return this; + } + + public OAuthClient state(String state) { + this.state = state; + return this; + } + + public OAuthClient scope(String scope) { + this.scope = scope; + return this; + } + + public OAuthClient uiLocales(String uiLocales){ + this.uiLocales = uiLocales; + return this; + } + + public OAuthClient clientSessionState(String client_session_state) { + this.clientSessionState = client_session_state; + return this; + } + + public OAuthClient clientSessionHost(String client_session_host) { + this.clientSessionHost = client_session_host; + return this; + } + + public String getRealm() { + return realm; + } + + public static class AuthorizationCodeResponse { + + private boolean isRedirected; + private String code; + private String state; + private String error; + + public AuthorizationCodeResponse(OAuthClient client) { + isRedirected = client.getCurrentRequest().equals(client.getRedirectUri()); + code = client.getCurrentQuery().get(OAuth2Constants.CODE); + state = client.getCurrentQuery().get(OAuth2Constants.STATE); + error = client.getCurrentQuery().get(OAuth2Constants.ERROR); + } + + public boolean isRedirected() { + return isRedirected; + } + + public String getCode() { + return code; + } + + public String getState() { + return state; + } + + public String getError() { + return error; + } + + } + + public static class AccessTokenResponse { + private int statusCode; + + private String accessToken; + private String tokenType; + private int expiresIn; + private int refreshExpiresIn; + private String refreshToken; + + private String error; + private String errorDescription; + + public AccessTokenResponse(HttpResponse response) throws Exception { + statusCode = response.getStatusLine().getStatusCode(); + if (!"application/json".equals(response.getHeaders("Content-Type")[0].getValue())) { + Assert.fail("Invalid content type"); + } + + String s = IOUtils.toString(response.getEntity().getContent()); + Map responseJson = JsonSerialization.readValue(s, Map.class); + + if (statusCode == 200) { + accessToken = (String)responseJson.get("access_token"); + tokenType = (String)responseJson.get("token_type"); + expiresIn = (Integer)responseJson.get("expires_in"); + refreshExpiresIn = (Integer)responseJson.get("refresh_expires_in"); + + if (responseJson.containsKey(OAuth2Constants.REFRESH_TOKEN)) { + refreshToken = (String)responseJson.get(OAuth2Constants.REFRESH_TOKEN); + } + } else { + error = (String)responseJson.get(OAuth2Constants.ERROR); + errorDescription = responseJson.containsKey(OAuth2Constants.ERROR_DESCRIPTION) ? (String)responseJson.get(OAuth2Constants.ERROR_DESCRIPTION) : null; + } + } + + public String getAccessToken() { + return accessToken; + } + + public String getError() { + return error; + } + + public String getErrorDescription() { + return errorDescription; + } + + public int getExpiresIn() { + return expiresIn; + } + + public int getRefreshExpiresIn() { + return refreshExpiresIn; + } + + public int getStatusCode() { + return statusCode; + } + + public String getRefreshToken() { + return refreshToken; + } + + public String getTokenType() { + return tokenType; + } + } + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json index 845adda955..beb1d85081 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/testrealm.json @@ -101,11 +101,11 @@ { "clientId": "test-app", "enabled": true, - "baseUrl": "http://localhost:8081/app", + "baseUrl": "http://localhost:8180/auth/realms/master/app", "redirectUris": [ - "http://localhost:8081/app/*" + "http://localhost:8180/auth/realms/master/app/*" ], - "adminUrl": "http://localhost:8081/app/logout", + "adminUrl": "http://localhost:8180/auth/realms/master/app/logout", "secret": "password" }, { @@ -114,7 +114,7 @@ "consentRequired": true, "redirectUris": [ - "http://localhost:8081/app/*" + "http://localhost:8180/app/*" ], "secret": "password" }