keycloak-aplcache
Changes
testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java 16(+16 -0)
testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProviderFactory.java 5(+4 -1)
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java 4(+4 -0)
Details
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
index d20d09f..7b76083 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProvider.java
@@ -19,6 +19,7 @@ package org.keycloak.testsuite.rest;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.BadRequestException;
+import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.events.Event;
@@ -48,6 +49,7 @@ import org.keycloak.representations.idm.AuthDetailsRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.scheduled.ClearExpiredUserSessions;
@@ -78,6 +80,8 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.Response;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -96,6 +100,9 @@ public class TestingResourceProvider implements RealmResourceProvider {
private final KeycloakSession session;
private final Map<String, TimerProvider.TimerTaskContext> suspendedTimerTasks;
+ @Context
+ private HttpRequest request;
+
@Override
public Object getResource() {
return this;
@@ -549,6 +556,15 @@ public class TestingResourceProvider implements RealmResourceProvider {
return details;
}
+ @GET
+ @Path("/get-sso-cookie")
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getSSOCookieValue() {
+ Map<String, Cookie> cookies = request.getHttpHeaders().getCookies();
+ return cookies.get(AuthenticationManager.KEYCLOAK_IDENTITY_COOKIE).getValue();
+ }
+
+
@Path("/cache/{cache}")
public TestCacheResource getCacheResource(@PathParam("cache") String cacheName) {
return new TestCacheResource(session, cacheName);
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProviderFactory.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProviderFactory.java
index d796c2f..e1a1f30 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProviderFactory.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/rest/TestingResourceProviderFactory.java
@@ -20,6 +20,7 @@ package org.keycloak.testsuite.rest;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.Config.Scope;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
@@ -36,7 +37,9 @@ public class TestingResourceProviderFactory implements RealmResourceProviderFact
@Override
public RealmResourceProvider create(KeycloakSession session) {
- return new TestingResourceProvider(session, suspendedTimerTasks);
+ TestingResourceProvider testProvider = new TestingResourceProvider(session, suspendedTimerTasks);
+ ResteasyProviderFactory.getInstance().injectProperties(testProvider);
+ return testProvider;
}
@Override
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java
index 7c61206..57b9afc 100755
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/KeycloakTestingClient.java
@@ -56,6 +56,10 @@ public class KeycloakTestingClient {
return new KeycloakTestingClient(serverUrl, null);
}
+ public static KeycloakTestingClient getInstance(String serverUrl, ResteasyClient resteasyClient) {
+ return new KeycloakTestingClient(serverUrl, resteasyClient);
+ }
+
public TestingResource testing() {
return target.path("/realms/master").proxy(TestingResource.class);
}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
index 8b551f0..dc6bfaf 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/client/resources/TestingResource.java
@@ -171,6 +171,11 @@ public interface TestingResource {
@Consumes(MediaType.APPLICATION_JSON)
void onAdminEvent(final AdminEventRepresentation rep, @QueryParam("includeRepresentation") boolean includeRepresentation);
+ @GET
+ @Path("/get-sso-cookie")
+ @Produces(MediaType.APPLICATION_JSON)
+ String getSSOCookieValue();
+
@POST
@Path("/remove-user-session")
@Produces(MediaType.APPLICATION_JSON)
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java
index 72421cc..c1e0f49 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ImpersonationTest.java
@@ -17,13 +17,18 @@
package org.keycloak.testsuite.admin;
+import org.jboss.arquillian.graphene.page.Page;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.Config;
import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.events.Details;
import org.keycloak.events.EventType;
@@ -34,12 +39,17 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
import org.keycloak.testsuite.auth.page.AuthRealm;
+import org.keycloak.testsuite.client.KeycloakTestingClient;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.util.ClientBuilder;
import org.keycloak.testsuite.util.CredentialBuilder;
+import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.RealmBuilder;
import org.keycloak.testsuite.util.UserBuilder;
@@ -50,6 +60,7 @@ import java.util.List;
import java.util.Map;
import org.junit.Assume;
import org.junit.BeforeClass;
+import org.openqa.selenium.Cookie;
/**
* Tests Undertow Adapter
@@ -61,6 +72,12 @@ public class ImpersonationTest extends AbstractKeycloakTest {
@Rule
public AssertEvents events = new AssertEvents(this);
+ @Page
+ protected AppPage appPage;
+
+ @Page
+ protected LoginPage loginPage;
+
private String impersonatedUserId;
@Override
@@ -147,25 +164,66 @@ public class ImpersonationTest extends AbstractKeycloakTest {
}
- protected void testSuccessfulImpersonation(String admin, String adminRealm) {
+ // KEYCLOAK-5981
+ @Test
+ public void testImpersonationWorksWhenAuthenticationSessionExists() throws Exception {
+ // Create test client
+ RealmResource realm = adminClient.realms().realm("test");
+ Response resp = realm.clients().create(ClientBuilder.create().clientId("test-app").addRedirectUri(OAuthClient.APP_ROOT + "/*").build());
+ resp.close();
+
+ // Open the URL for the client (will redirect to Keycloak server AuthorizationEndpoint and create authenticationSession)
+ String loginFormUrl = oauth.getLoginFormUrl();
+ driver.navigate().to(loginFormUrl);
+ loginPage.assertCurrent();
+
+ // Impersonate and get SSO cookie. Setup that cookie for webDriver
+ String ssoCookie = testSuccessfulImpersonation("realm-admin", "test");
+ driver.manage().addCookie(new Cookie(AuthenticationManager.KEYCLOAK_IDENTITY_COOKIE, ssoCookie));
+
+ // Open the URL again - should be directly redirected to the app due the SSO login
+ driver.navigate().to(loginFormUrl);
+ appPage.assertCurrent();
+
+ // Remove test client
+ ApiUtil.findClientByClientId(realm, "test-app").remove();
+ }
+
+
+ // Return the SSO cookie from the impersonated session
+ protected String testSuccessfulImpersonation(String admin, String adminRealm) {
+ ResteasyClient resteasyClient = new ResteasyClientBuilder().connectionPoolSize(10).build();
- Keycloak client = login(admin, adminRealm);
+ // Login adminClient
+ Keycloak client = login(admin, adminRealm, resteasyClient);
try {
- Map data = client.realms().realm("test").users().get(impersonatedUserId).impersonate();
- Assert.assertNotNull(data);
- Assert.assertNotNull(data.get("redirect"));
-
- events.expect(EventType.IMPERSONATE)
- .session(AssertEvents.isUUID())
- .user(impersonatedUserId)
- .detail(Details.IMPERSONATOR, admin)
- .detail(Details.IMPERSONATOR_REALM, adminRealm)
- .client((String) null).assertEvent();
+ // Impersonate
+ impersonate(client, admin, adminRealm);
+
+ // Get the SSO cookie. Needs to use same RestEasyClient used by adminClient to be able to see the cookies
+ KeycloakTestingClient testingClient = KeycloakTestingClient.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth", resteasyClient);
+ String kcIdentity = testingClient.testing("test").getSSOCookieValue();
+ Assert.assertNotNull(kcIdentity);
+
+ return kcIdentity;
} finally {
- client.close();
+ resteasyClient.close();
}
}
+ private void impersonate(Keycloak adminClient, String admin, String adminRealm) {
+ Map data = adminClient.realms().realm("test").users().get(impersonatedUserId).impersonate();
+ Assert.assertNotNull(data);
+ Assert.assertNotNull(data.get("redirect"));
+
+ events.expect(EventType.IMPERSONATE)
+ .session(AssertEvents.isUUID())
+ .user(impersonatedUserId)
+ .detail(Details.IMPERSONATOR, admin)
+ .detail(Details.IMPERSONATOR_REALM, adminRealm)
+ .client((String) null).assertEvent();
+ }
+
protected void testForbiddenImpersonation(String admin, String adminRealm) {
Keycloak client = createAdminClient(adminRealm, establishClientId(adminRealm), admin);
try {
@@ -178,24 +236,30 @@ public class ImpersonationTest extends AbstractKeycloakTest {
}
Keycloak createAdminClient(String realm, String clientId, String username) {
- return createAdminClient(realm, clientId, username, null);
+ return createAdminClient(realm, clientId, username, null, null);
}
String establishClientId(String realm) {
return realm.equals("master") ? Constants.ADMIN_CLI_CLIENT_ID : "myclient";
}
- Keycloak createAdminClient(String realm, String clientId, String username, String password) {
+ Keycloak createAdminClient(String realm, String clientId, String username, String password, ResteasyClient resteasyClient) {
if (password == null) {
password = username.equals("admin") ? "admin" : "password";
}
- return Keycloak.getInstance(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth",
- realm, username, password, clientId);
+
+ return KeycloakBuilder.builder().serverUrl(AuthServerTestEnricher.getAuthServerContextRoot() + "/auth")
+ .realm(realm)
+ .username(username)
+ .password(password)
+ .clientId(clientId)
+ .resteasyClient(resteasyClient)
+ .build();
}
- private Keycloak login(String username, String realm) {
+ private Keycloak login(String username, String realm, ResteasyClient resteasyClient) {
String clientId = establishClientId(realm);
- Keycloak client = createAdminClient(realm, clientId, username);
+ Keycloak client = createAdminClient(realm, clientId, username, null, resteasyClient);
client.tokenManager().grantToken();
// only poll for LOGIN event if realm is not master