diff --git a/misc/keycloak-test-helper/pom.xml b/misc/keycloak-test-helper/pom.xml new file mode 100644 index 0000000000..bbf89f83eb --- /dev/null +++ b/misc/keycloak-test-helper/pom.xml @@ -0,0 +1,38 @@ + + + + 4.0.0 + + keycloak-misc-parent + org.keycloak + 3.0.0.CR1-SNAPSHOT + ../pom.xml + + org.keycloak + keycloak-test-helper + keycloak-test-helper + Helper library to test application using Keycloak. + jar + + + org.keycloak + keycloak-client-registration-api + 3.0.0.CR1-SNAPSHOT + + + org.keycloak + keycloak-admin-client + 3.0.0.CR1-SNAPSHOT + + + org.jboss.resteasy + resteasy-client + 3.0.7.Final + + + org.jboss.resteasy + resteasy-jackson2-provider + 3.0.7.Final + + + diff --git a/misc/keycloak-test-helper/src/main/java/org/keycloak/helper/TestsHelper.java b/misc/keycloak-test-helper/src/main/java/org/keycloak/helper/TestsHelper.java new file mode 100644 index 0000000000..4beb57af41 --- /dev/null +++ b/misc/keycloak-test-helper/src/main/java/org/keycloak/helper/TestsHelper.java @@ -0,0 +1,272 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2017, Red Hat, Inc. and/or its affiliates, and individual + * contributors by the @authors tag. See the copyright.txt in the + * distribution for a full listing of individual contributors. + * + * 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.helper; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.client.registration.Auth; +import org.keycloak.client.registration.ClientRegistration; +import org.keycloak.client.registration.ClientRegistrationException; +import org.keycloak.representations.idm.ClientRepresentation; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.Arrays; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation; +import org.keycloak.representations.idm.ClientInitialAccessPresentation; +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.representations.idm.RoleRepresentation; +import org.keycloak.representations.idm.UserRepresentation; + +public class TestsHelper { + + public static String baseUrl; + + public static String keycloakBaseUrl = "http://localhost:8180/auth"; + + public static String testRealm = "test-realm"; + + public static String initialAccessCode; + + public static String appName; + + protected static String clientConfiguration; + + protected static String registrationAccessCode; + + public static String createClient(ClientRepresentation clientRepresentation) { + ClientRegistration reg = ClientRegistration.create() + .url(keycloakBaseUrl, testRealm) + .build(); + + reg.auth(Auth.token(initialAccessCode)); + try { + clientRepresentation = reg.create(clientRepresentation); + registrationAccessCode = clientRepresentation.getRegistrationAccessToken(); + ObjectMapper mapper = new ObjectMapper(); + reg.auth(Auth.token(registrationAccessCode)); + clientConfiguration = mapper.writeValueAsString(reg.getAdapterConfig(clientRepresentation.getClientId())); + } catch (ClientRegistrationException e) { + e.printStackTrace(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + return clientConfiguration; + } + + public static String createDirectGrantClient() { + ClientRepresentation clientRepresentation = new ClientRepresentation(); + clientRepresentation.setClientId("test-dga"); + clientRepresentation.setFullScopeAllowed(true); + clientRepresentation.setPublicClient(Boolean.TRUE); + clientRepresentation.setDirectAccessGrantsEnabled(true); + + ClientRegistration reg = ClientRegistration.create() + .url(keycloakBaseUrl, testRealm) + .build(); + + reg.auth(Auth.token(initialAccessCode)); + try { + clientRepresentation = reg.create(clientRepresentation); + registrationAccessCode = clientRepresentation.getRegistrationAccessToken(); + ObjectMapper mapper = new ObjectMapper(); + reg.auth(Auth.token(registrationAccessCode)); + clientConfiguration = mapper.writeValueAsString(reg.getAdapterConfig(clientRepresentation.getClientId())); + } catch (ClientRegistrationException e) { + e.printStackTrace(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + + return clientConfiguration; + } + + public static void deleteClient(String clientId) { + ClientRegistration reg = ClientRegistration.create() + .url(keycloakBaseUrl, testRealm) + .build(); + try { + reg.auth(Auth.token(registrationAccessCode)); + reg.delete(clientId); + } catch (ClientRegistrationException e) { + e.printStackTrace(); + } + } + + public static boolean testGetWithAuth(String endpoint, String token) throws IOException { + CloseableHttpClient client = HttpClientBuilder.create().build(); + + try { + HttpGet get = new HttpGet(baseUrl + endpoint); + get.addHeader("Authorization", "Bearer " + token); + + HttpResponse response = client.execute(get); + if (response.getStatusLine().getStatusCode() != 200) { + return false; + } + HttpEntity entity = response.getEntity(); + InputStream is = entity.getContent(); + try { + return true; + } finally { + is.close(); + } + + } finally { + client.close(); + } + } + + public static boolean returnsForbidden(String endpoint) throws IOException { + CloseableHttpClient client = HttpClientBuilder.create().build(); + try { + HttpGet get = new HttpGet(baseUrl + endpoint); + HttpResponse response = client.execute(get); + if (response.getStatusLine().getStatusCode() == 403 || response.getStatusLine().getStatusCode() == 401) { + return true; + } else { + return false; + } + + } finally { + client.close(); + } + } + + public static String getToken(String username, String password, String realm) { + Keycloak keycloak = Keycloak.getInstance( + keycloakBaseUrl, + realm, + username, + password, + "test-dga"); + return keycloak.tokenManager().getAccessTokenString(); + + } + + public static boolean ImportTestRealm(String username, String password, String realmJsonPath) throws IOException { + + ObjectMapper mapper = new ObjectMapper(); + ClassLoader classLoader = TestsHelper.class.getClassLoader(); + InputStream stream = TestsHelper.class.getResourceAsStream(realmJsonPath); + RealmRepresentation realmRepresentation = mapper.readValue(stream, RealmRepresentation.class); + + Keycloak keycloak = Keycloak.getInstance( + keycloakBaseUrl, + "master", + username, + password, + "admin-cli"); + keycloak.realms().create(realmRepresentation); + testRealm = realmRepresentation.getRealm(); + ClientInitialAccessCreatePresentation rep = new ClientInitialAccessCreatePresentation(); + rep.setCount(2); + rep.setExpiration(100); + ClientInitialAccessPresentation initialAccess = keycloak.realms().realm(testRealm).clientInitialAccess().create(rep); + initialAccessCode = initialAccess.getToken(); + return true; + + } + + public static boolean ImportTestRealm(String username, String password) throws IOException { + testRealm = appName + "-realm"; + RealmRepresentation realmRepresentation = new RealmRepresentation(); + realmRepresentation.setRealm(testRealm); + realmRepresentation.setEnabled(true); + Keycloak keycloak = Keycloak.getInstance( + keycloakBaseUrl, + "master", + username, + password, + "admin-cli"); + keycloak.realms().create(realmRepresentation); + ClientInitialAccessCreatePresentation rep = new ClientInitialAccessCreatePresentation(); + rep.setCount(2); + rep.setExpiration(100); + ClientInitialAccessPresentation initialAccess = keycloak.realms().realm(testRealm).clientInitialAccess().create(rep); + initialAccessCode = initialAccess.getToken(); + return true; + } + + public static boolean deleteRealm(String username, String password, String realmName) throws IOException { + + Keycloak keycloak = Keycloak.getInstance( + keycloakBaseUrl, + "master", + username, + password, + "admin-cli"); + keycloak.realms().realm(realmName).remove(); + return true; + + } + + public static boolean createTestUser(String username, String password, String realmName) throws IOException { + + Keycloak keycloak = Keycloak.getInstance( + keycloakBaseUrl, + "master", + username, + password, + "admin-cli"); + UserRepresentation userRepresentation = new UserRepresentation(); + userRepresentation.setUsername("testuser"); + userRepresentation.setEnabled(Boolean.TRUE); + Response response = keycloak.realms().realm(realmName).users().create(userRepresentation); + String userId = getCreatedId(response); + response.close(); + CredentialRepresentation rep = new CredentialRepresentation(); + rep.setType(CredentialRepresentation.PASSWORD); + rep.setValue("password"); + rep.setTemporary(false); + keycloak.realms().realm(realmName).users().get(userId).resetPassword(rep); + //add roles + RoleRepresentation representation = new RoleRepresentation(); + representation.setName("user"); + keycloak.realms().realm(realmName).roles().create(representation); + RoleRepresentation realmRole = keycloak.realms().realm(realmName).roles().get("user").toRepresentation(); + keycloak.realms().realm(realmName).users().get(userId).roles().realmLevel().add(Arrays.asList(realmRole)); + return true; + + } + + public static String getCreatedId(Response response) { + URI location = response.getLocation(); + if (!response.getStatusInfo().equals(Response.Status.CREATED)) { + Response.StatusType statusInfo = response.getStatusInfo(); + throw new WebApplicationException("Create method returned status " + + statusInfo.getReasonPhrase() + " (Code: " + statusInfo.getStatusCode() + "); expected status: Created (201)", response); + } + if (location == null) { + return null; + } + String path = location.getPath(); + return path.substring(path.lastIndexOf('/') + 1); + } + +} diff --git a/misc/pom.xml b/misc/pom.xml index c5332d3f46..d4005ca0f8 100644 --- a/misc/pom.xml +++ b/misc/pom.xml @@ -14,5 +14,6 @@ pom spring-boot-starter + keycloak-test-helper