diff --git a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AbstractSpringBootTest.java b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AbstractSpringBootTest.java index 21eacfa60f..5b15077719 100644 --- a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AbstractSpringBootTest.java +++ b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AbstractSpringBootTest.java @@ -7,6 +7,7 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -35,6 +36,8 @@ import org.openqa.selenium.By; public abstract class AbstractSpringBootTest extends AbstractKeycloakTest { + protected static final String REALM_ID = "cd8ee421-5100-41ba-95dd-b27c8e5cf042"; + protected static final String REALM_NAME = "test"; protected static final String CLIENT_ID = "spring-boot-app"; @@ -84,6 +87,7 @@ public abstract class AbstractSpringBootTest extends AbstractKeycloakTest { public void addTestRealms(List testRealms) { RealmRepresentation realm = new RealmRepresentation(); + realm.setId(REALM_ID); realm.setRealm(REALM_NAME); realm.setEnabled(true); @@ -92,6 +96,11 @@ public abstract class AbstractSpringBootTest extends AbstractKeycloakTest { realm.setClients(Collections.singletonList(createClient())); + List eventListeners = new ArrayList<>(); + eventListeners.add("jboss-logging"); + eventListeners.add("event-queue"); + realm.setEventsListeners(eventListeners); + testRealms.add(realm); } @@ -158,6 +167,11 @@ public abstract class AbstractSpringBootTest extends AbstractKeycloakTest { WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); } + protected String getCorrectUserId() { + return adminClient.realms().realm(REALM_NAME).users().search(USER_LOGIN) + .get(0).getId(); + } + @Before public void createRoles() { RealmResource realm = realmsResouce().realm(REALM_NAME); diff --git a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java new file mode 100644 index 0000000000..5ac950f767 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/OfflineTokenSpringBootTest.java @@ -0,0 +1,154 @@ +package org.keycloak.testsuite.springboot; + +import org.jboss.arquillian.graphene.page.Page; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.keycloak.OAuth2Constants; +import org.keycloak.events.Details; +import org.keycloak.events.EventType; +import org.keycloak.services.Urls; +import org.keycloak.testsuite.AssertEvents; +import org.keycloak.testsuite.pages.AccountApplicationsPage; +import org.keycloak.testsuite.pages.OAuthGrantPage; +import org.keycloak.testsuite.util.ClientManager; +import org.keycloak.testsuite.util.WaitUtils; +import org.keycloak.util.TokenUtil; +import org.openqa.selenium.By; + +import javax.ws.rs.core.UriBuilder; +import java.util.List; + +import static org.keycloak.testsuite.util.WaitUtils.pause; + +public class OfflineTokenSpringBootTest extends AbstractSpringBootTest { + private static final String SERVLET_URI = APPLICATION_URL + "/admin/TokenServlet"; + + @Rule + public AssertEvents events = new AssertEvents(this); + + @Page + private AccountApplicationsPage accountAppPage; + + @Page + private OAuthGrantPage oauthGrantPage; + + @Test + public void testTokens() { + String servletUri = UriBuilder.fromUri(SERVLET_URI) + .queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS) + .build().toString(); + driver.navigate().to(servletUri); + + Assert.assertTrue("Must be on login page", loginPage.isCurrent()); + loginPage.login(USER_LOGIN, USER_PASSWORD); + + WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); + + Assert.assertTrue(tokenPage.isCurrent()); + + Assert.assertEquals(tokenPage.getRefreshToken().getType(), TokenUtil.TOKEN_TYPE_OFFLINE); + Assert.assertEquals(tokenPage.getRefreshToken().getExpiration(), 0); + + String accessTokenId = tokenPage.getAccessToken().getId(); + String refreshTokenId = tokenPage.getRefreshToken().getId(); + + setAdapterAndServerTimeOffset(9999, SERVLET_URI); + + driver.navigate().to(SERVLET_URI); + Assert.assertTrue("Must be on tokens page", tokenPage.isCurrent()); + Assert.assertNotEquals(tokenPage.getRefreshToken().getId(), refreshTokenId); + Assert.assertNotEquals(tokenPage.getAccessToken().getId(), accessTokenId); + + setAdapterAndServerTimeOffset(0, SERVLET_URI); + + driver.navigate().to(logoutPage(SERVLET_URI)); + Assert.assertTrue("Must be on login page", loginPage.isCurrent()); + } + + @Test + public void testRevoke() { + // Login to servlet first with offline token + String servletUri = UriBuilder.fromUri(SERVLET_URI) + .queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS) + .build().toString(); + driver.navigate().to(servletUri); + WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); + + loginPage.login(USER_LOGIN, USER_PASSWORD); + Assert.assertTrue("Must be on token page", tokenPage.isCurrent()); + + Assert.assertEquals(tokenPage.getRefreshToken().getType(), TokenUtil.TOKEN_TYPE_OFFLINE); + + // Assert refresh works with increased time + setAdapterAndServerTimeOffset(9999, SERVLET_URI); + driver.navigate().to(SERVLET_URI); + Assert.assertTrue("Must be on token page", tokenPage.isCurrent()); + setAdapterAndServerTimeOffset(0, SERVLET_URI); + + events.clear(); + + // Go to account service and revoke grant + accountAppPage.open(); + + List additionalGrants = accountAppPage.getApplications().get(CLIENT_ID).getAdditionalGrants(); + Assert.assertEquals(additionalGrants.size(), 1); + Assert.assertEquals(additionalGrants.get(0), "Offline Token"); + accountAppPage.revokeGrant(CLIENT_ID); + pause(500); + Assert.assertEquals(accountAppPage.getApplications().get(CLIENT_ID).getAdditionalGrants().size(), 0); + + events.expect(EventType.REVOKE_GRANT).realm(REALM_ID).user(getCorrectUserId()) + .client("account").detail(Details.REVOKED_CLIENT, CLIENT_ID).assertEvent(); + + // Assert refresh doesn't work now (increase time one more time) + setAdapterAndServerTimeOffset(9999, SERVLET_URI); + driver.navigate().to(SERVLET_URI); + loginPage.assertCurrent(); + setAdapterAndServerTimeOffset(0, SERVLET_URI); + } + + @Test + public void testConsent() { + ClientManager.realm(adminClient.realm(REALM_NAME)).clientId(CLIENT_ID).consentRequired(true); + + // Assert grant page doesn't have 'Offline Access' role when offline token is not requested + driver.navigate().to(SERVLET_URI); + loginPage.login(USER_LOGIN, USER_PASSWORD); + oauthGrantPage.assertCurrent(); + WaitUtils.waitUntilElement(By.xpath("//body")).text().not().contains("Offline access"); + oauthGrantPage.cancel(); + + // Assert grant page has 'Offline Access' role now + String servletUri = UriBuilder.fromUri(SERVLET_URI) + .queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS) + .build().toString(); + driver.navigate().to(servletUri); + WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); + + loginPage.login(USER_LOGIN, USER_PASSWORD); + oauthGrantPage.assertCurrent(); + WaitUtils.waitUntilElement(By.xpath("//body")).text().contains("Offline access"); + + oauthGrantPage.accept(); + + Assert.assertTrue("Must be on token page", tokenPage.isCurrent()); + Assert.assertEquals(tokenPage.getRefreshToken().getType(), TokenUtil.TOKEN_TYPE_OFFLINE); + + String accountAppPageUrl = + Urls.accountApplicationsPage(getAuthServerRoot(), REALM_NAME).toString(); + driver.navigate().to(accountAppPageUrl); + AccountApplicationsPage.AppEntry offlineClient = accountAppPage.getApplications().get(CLIENT_ID); + Assert.assertTrue(offlineClient.getRolesGranted().contains("Offline access")); + Assert.assertTrue(offlineClient.getAdditionalGrants().contains("Offline Token")); + + //This was necessary to be introduced, otherwise other testcases will fail + driver.navigate().to(logoutPage(SERVLET_URI)); + loginPage.assertCurrent(); + + events.clear(); + + // Revert change + ClientManager.realm(adminClient.realm(REALM_NAME)).clientId(CLIENT_ID).consentRequired(false); + } +} diff --git a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/TokenSpringBootTest.java b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/TokenSpringBootTest.java deleted file mode 100644 index 9c86e8a638..0000000000 --- a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/TokenSpringBootTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.keycloak.testsuite.springboot; - -import org.junit.Assert; -import org.junit.Test; -import org.keycloak.OAuth2Constants; -import org.keycloak.testsuite.util.WaitUtils; -import org.keycloak.util.TokenUtil; -import org.openqa.selenium.By; - -public class TokenSpringBootTest extends AbstractSpringBootTest { - @Test - public void testTokens() { - String servletUri = APPLICATION_URL + "/admin/TokenServlet"; - - driver.navigate().to(servletUri + "?" + OAuth2Constants.SCOPE + "=" + OAuth2Constants.OFFLINE_ACCESS); - - Assert.assertTrue("Must be on login page", loginPage.isCurrent()); - loginPage.login(USER_LOGIN, USER_PASSWORD); - - WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); - - Assert.assertTrue(tokenPage.isCurrent()); - - Assert.assertEquals(tokenPage.getRefreshToken().getType(), TokenUtil.TOKEN_TYPE_OFFLINE); - Assert.assertEquals(tokenPage.getRefreshToken().getExpiration(), 0); - - String accessTokenId = tokenPage.getAccessToken().getId(); - String refreshTokenId = tokenPage.getRefreshToken().getId(); - - setAdapterAndServerTimeOffset(9999, servletUri); - - driver.navigate().to(servletUri); - Assert.assertTrue("Must be on tokens page", tokenPage.isCurrent()); - Assert.assertNotEquals(tokenPage.getRefreshToken().getId(), refreshTokenId); - Assert.assertNotEquals(tokenPage.getAccessToken().getId(), accessTokenId); - - setAdapterAndServerTimeOffset(0, servletUri); - - driver.navigate().to(logoutPage(servletUri)); - Assert.assertTrue("Must be on login page", loginPage.isCurrent()); - } -}