/* * 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.adapter.servlet; import org.apache.commons.io.FileUtils; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.graphene.page.Page; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.common.Version; import org.keycloak.common.util.Time; import org.keycloak.constants.AdapterConstants; import org.keycloak.events.Details; import org.keycloak.events.EventType; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.representations.AccessToken; import org.keycloak.representations.VersionRepresentation; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.AssertEvents; import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest; import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter; import org.keycloak.testsuite.adapter.page.*; import org.keycloak.testsuite.admin.ApiUtil; import org.keycloak.testsuite.auth.page.account.Applications; import org.keycloak.testsuite.auth.page.login.OAuthGrant; import org.keycloak.testsuite.console.page.events.Config; import org.keycloak.testsuite.console.page.events.LoginEvents; import org.keycloak.testsuite.util.*; import org.keycloak.testsuite.util.URLUtils; import org.keycloak.util.BasicAuthHelper; import org.openqa.selenium.By; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Form; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.junit.Assert.*; import javax.ws.rs.core.Response.Status; import static org.hamcrest.Matchers.*; import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf; import static org.keycloak.testsuite.util.WaitUtils.*; /** * * @author tkyjovsk */ public abstract class AbstractDemoServletsAdapterTest extends AbstractServletsAdapterTest { @Page private CustomerPortal customerPortal; @Page private CustomerPortalNoConf customerPortalNoConf; @Page private SecurePortal securePortal; @Page private SecurePortalWithCustomSessionConfig securePortalWithCustomSessionConfig; @Page private CustomerDb customerDb; @Page private CustomerDbErrorPage customerDbErrorPage; @Page private ProductPortal productPortal; @Page private InputPortal inputPortal; @Page private TokenMinTTLPage tokenMinTTLPage; @Page private OAuthGrant oAuthGrantPage; @Page private Applications applicationsPage; @Page private LoginEvents loginEventsPage; @Page private BasicAuth basicAuthPage; @Page private Config configPage; @Rule public AssertEvents assertEvents = new AssertEvents(this); @Deployment(name = CustomerPortal.DEPLOYMENT_NAME) protected static WebArchive customerPortal() { return servletDeployment(CustomerPortal.DEPLOYMENT_NAME, CustomerServlet.class, ErrorServlet.class, ServletTestUtils.class); } @Deployment(name = CustomerPortalNoConf.DEPLOYMENT_NAME) protected static WebArchive customerPortalNoConf() { return servletDeployment(CustomerPortalNoConf.DEPLOYMENT_NAME, CustomerServletNoConf.class, ErrorServlet.class); } @Deployment(name = SecurePortal.DEPLOYMENT_NAME) protected static WebArchive securePortal() { return servletDeployment(SecurePortal.DEPLOYMENT_NAME, CallAuthenticatedServlet.class); } @Deployment(name = SecurePortalWithCustomSessionConfig.DEPLOYMENT_NAME) protected static WebArchive securePortalWithCustomSessionConfig() { return servletDeployment(SecurePortalWithCustomSessionConfig.DEPLOYMENT_NAME, CallAuthenticatedServlet.class); } @Deployment(name = CustomerDb.DEPLOYMENT_NAME) protected static WebArchive customerDb() { return servletDeployment(CustomerDb.DEPLOYMENT_NAME, AdapterActionsFilter.class, CustomerDatabaseServlet.class); } @Deployment(name = CustomerDbErrorPage.DEPLOYMENT_NAME) protected static WebArchive customerDbErrorPage() { return servletDeployment(CustomerDbErrorPage.DEPLOYMENT_NAME, CustomerDatabaseServlet.class, ErrorServlet.class); } @Deployment(name = ProductPortal.DEPLOYMENT_NAME) protected static WebArchive productPortal() { return servletDeployment(ProductPortal.DEPLOYMENT_NAME, ProductServlet.class); } @Deployment(name = InputPortal.DEPLOYMENT_NAME) protected static WebArchive inputPortal() { return servletDeployment(InputPortal.DEPLOYMENT_NAME, "keycloak.json", InputServlet.class, ServletTestUtils.class); } @Deployment(name = TokenMinTTLPage.DEPLOYMENT_NAME) protected static WebArchive tokenMinTTLPage() { return servletDeployment(TokenMinTTLPage.DEPLOYMENT_NAME, AdapterActionsFilter.class, AbstractShowTokensServlet.class, TokenMinTTLServlet.class, ErrorServlet.class); } @Deployment(name = BasicAuth.DEPLOYMENT_NAME) protected static WebArchive basicAuth() { return servletDeployment(BasicAuth.DEPLOYMENT_NAME, BasicAuthServlet.class); } @Override public void setDefaultPageUriParameters() { super.setDefaultPageUriParameters(); configPage.setConsoleRealm(DEMO); loginEventsPage.setConsoleRealm(DEMO); applicationsPage.setAuthRealm(DEMO); loginEventsPage.setConsoleRealm(DEMO); } @Before public void beforeDemoServletsAdapterTest() { // Delete all cookies from token-min-ttl page to be sure we are logged out tokenMinTTLPage.navigateTo(); driver.manage().deleteAllCookies(); } @Test public void testSavedPostRequest() throws InterruptedException { // test login to customer-portal which does a bearer request to customer-db inputPortal.navigateTo(); assertCurrentUrlEquals(inputPortal); inputPortal.execute("hello"); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(driver, inputPortal + "/secured/post"); waitForPageToLoad(driver); String pageSource = driver.getPageSource(); assertThat(pageSource, containsString("parameter=hello")); String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) .queryParam(OAuth2Constants.REDIRECT_URI, customerPortal.toString()) .build("demo").toString(); driver.navigate().to(logoutUri); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); productPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); customerPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); // test unsecured POST KEYCLOAK-901 Client client = ClientBuilder.newClient(); Form form = new Form(); form.param("parameter", "hello"); String text = client.target(inputPortal + "/unsecured").request().post(Entity.form(form), String.class); assertTrue(text.contains("parameter=hello")); client.close(); } @Test public void testLoginSSOAndLogout() { // test login to customer-portal which does a bearer request to customer-db customerPortal.navigateTo(); testRealmLoginPage.form().waitForUsernameInputPresent(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(customerPortal); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); // test SSO productPortal.navigateTo(); assertCurrentUrlEquals(productPortal); pageSource = driver.getPageSource(); assertTrue(pageSource.contains("iPhone") && pageSource.contains("iPad")); // View stats List<Map<String, String>> stats = testRealmResource().getClientSessionStats(); Map<String, String> customerPortalStats = null; Map<String, String> productPortalStats = null; for (Map<String, String> s : stats) { switch (s.get("clientId")) { case "customer-portal": customerPortalStats = s; break; case "product-portal": productPortalStats = s; break; } } assertEquals(1, Integer.parseInt(customerPortalStats.get("active"))); assertEquals(1, Integer.parseInt(productPortalStats.get("active"))); // test logout String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) .queryParam(OAuth2Constants.REDIRECT_URI, customerPortal.toString()).build("demo").toString(); driver.navigate().to(logoutUri); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); productPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); customerPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); // testRealmLoginPage.form().cancel(); // assertTrue(driver.getPageSource().contains("Error Page")); } @Test public void testServletRequestLogout() { // test login to customer-portal which does a bearer request to customer-db customerPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(customerPortal); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); // test SSO productPortal.navigateTo(); assertCurrentUrlEquals(productPortal); pageSource = driver.getPageSource(); assertTrue(pageSource.contains("iPhone") && pageSource.contains("iPad")); // back customerPortal.navigateTo(); assertCurrentUrlEquals(customerPortal); pageSource = driver.getPageSource(); Assert.assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); // test logout driver.navigate().to(customerPortal + "/logout"); pageSource = driver.getPageSource(); assertTrue(pageSource.contains("servlet logout ok")); assertTrue(pageSource.contains("servlet logout from database ok")); customerPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); productPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); } @Test public void testLoginSSOIdle() { // test login to customer-portal which does a bearer request to customer-db customerPortal.navigateTo(); testRealmLoginPage.form().waitForUsernameInputPresent(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(customerPortal); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); RealmRepresentation demoRealmRep = testRealmResource().toRepresentation(); int originalIdle = demoRealmRep.getSsoSessionIdleTimeout(); demoRealmRep.setSsoSessionIdleTimeout(1); testRealmResource().update(demoRealmRep); pause(2000); productPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); demoRealmRep.setSsoSessionIdleTimeout(originalIdle); testRealmResource().update(demoRealmRep); } @Test public void testLoginSSOIdleRemoveExpiredUserSessions() { // test login to customer-portal which does a bearer request to customer-db customerPortal.navigateTo(); log.info("Current url: " + driver.getCurrentUrl()); testRealmLoginPage.form().waitForUsernameInputPresent(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); log.info("Current url: " + driver.getCurrentUrl()); assertCurrentUrlEquals(customerPortal); String pageSource = driver.getPageSource(); log.info(pageSource); Assert.assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); RealmRepresentation demoRealmRep = testRealmResource().toRepresentation(); int originalIdle = demoRealmRep.getSsoSessionIdleTimeout(); demoRealmRep.setSsoSessionIdleTimeout(1); testRealmResource().update(demoRealmRep); pause(2000); productPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); // need to cleanup so other tests don't fail, so invalidate http sessions on remote clients. demoRealmRep.setSsoSessionIdleTimeout(originalIdle); testRealmResource().update(demoRealmRep); // note: sessions invalidated after each test, see: AbstractKeycloakTest.afterAbstractKeycloakTest() } @Test public void testLoginSSOMax() throws InterruptedException { // Delete cookies driver.navigate().to(customerPortal + "/error.html"); driver.manage().deleteAllCookies(); // test login to customer-portal which does a bearer request to customer-db customerPortal.navigateTo(); testRealmLoginPage.form().waitForUsernameInputPresent(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(customerPortal); String pageSource = driver.getPageSource(); Assert.assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); RealmRepresentation demoRealmRep = testRealmResource().toRepresentation(); int originalMax = demoRealmRep.getSsoSessionMaxLifespan(); demoRealmRep.setSsoSessionMaxLifespan(1); testRealmResource().update(demoRealmRep); TimeUnit.SECONDS.sleep(2); productPortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); demoRealmRep.setSsoSessionMaxLifespan(originalMax); testRealmResource().update(demoRealmRep); String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) .queryParam(OAuth2Constants.REDIRECT_URI, securePortal.toString()).build("demo").toString(); driver.navigate().to(logoutUri); } @Test public void testNullBearerToken() { Client client = ClientBuilder.newClient(); WebTarget target = client.target(customerDb.toString()); Response response = target.request().get(); assertEquals(401, response.getStatus()); response.close(); response = target.request().header(HttpHeaders.AUTHORIZATION, "Bearer null").get(); assertEquals(401, response.getStatus()); response.close(); client.close(); } @Test @Ignore public void testNullBearerTokenCustomErrorPage() { Client client = ClientBuilder.newClient(); WebTarget target = client.target(customerDbErrorPage.toString()); Response response = target.request().get(); // TODO: follow redirects automatically if possible if (response.getStatus() == 302) { String location = response.getHeaderString(HttpHeaders.LOCATION); response.close(); response = client.target(location).request().get(); } assertEquals(200, response.getStatus()); String errorPageResponse = response.readEntity(String.class); assertTrue(errorPageResponse.contains("Error Page")); response.close(); response = target.request().header(HttpHeaders.AUTHORIZATION, "Bearer null").get(); // TODO: follow redirects automatically if possible if (response.getStatus() == 302) { String location = response.getHeaderString(HttpHeaders.LOCATION); response.close(); response = client.target(location).request().get(); } assertEquals(200, response.getStatus()); errorPageResponse = response.readEntity(String.class); assertTrue(errorPageResponse.contains("Error Page")); response.close(); client.close(); } @Test @Ignore public void testBadUser() { Client client = ClientBuilder.newClient(); URI uri = OIDCLoginProtocolService.tokenUrl(authServerPage.createUriBuilder()).build("demo"); WebTarget target = client.target(uri); String header = BasicAuthHelper.createHeader("customer-portal", "password"); Form form = new Form(); form.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD) .param("username", "monkey@redhat.com") .param("password", "password"); Response response = target.request() .header(HttpHeaders.AUTHORIZATION, header) .post(Entity.form(form)); assertEquals(401, response.getStatus()); response.close(); client.close(); } @Test public void testVersion() { Client client = ClientBuilder.newClient(); WebTarget target = client.target(authServerPage.createUriBuilder()).path("version"); VersionRepresentation version = target.request().get(VersionRepresentation.class); assertNotNull(version); assertNotNull(version.getVersion()); assertNotNull(version.getBuildTime()); assertNotEquals(version.getVersion(), Version.UNKNOWN); assertNotEquals(version.getBuildTime(), Version.UNKNOWN); VersionRepresentation version2 = client.target(securePortal.toString()).path(AdapterConstants.K_VERSION).request().get(VersionRepresentation.class); assertNotNull(version2); assertNotNull(version2.getVersion()); assertNotNull(version2.getBuildTime()); if (!suiteContext.isAdapterCompatTesting()) { assertEquals(version.getVersion(), version2.getVersion()); assertEquals(version.getBuildTime(), version2.getBuildTime()); } client.close(); } @Test public void testAuthenticated() { // test login to customer-portal which does a bearer request to customer-db securePortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(securePortal); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); // test logout String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) .queryParam(OAuth2Constants.REDIRECT_URI, securePortal.toString()).build("demo").toString(); driver.navigate().to(logoutUri); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); securePortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); } @Test public void testAuthenticatedWithCustomSessionConfig() { // test login to customer-portal which does a bearer request to customer-db securePortalWithCustomSessionConfig.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(securePortalWithCustomSessionConfig); assertThat("Cookie CUSTOM_JSESSION_ID_NAME should exist", driver.manage().getCookieNamed("CUSTOM_JSESSION_ID_NAME"), notNullValue()); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); // test logout String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) .queryParam(OAuth2Constants.REDIRECT_URI, securePortalWithCustomSessionConfig.toString()).build("demo").toString(); driver.navigate().to(logoutUri); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); securePortalWithCustomSessionConfig.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); } // Tests "token-minimum-time-to-live" adapter configuration option @Test public void testTokenMinTTL() { // Login tokenMinTTLPage.navigateTo(); testRealmLoginPage.form().waitForUsernameInputPresent(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(tokenMinTTLPage); // Get time of token AccessToken token = tokenMinTTLPage.getAccessToken(); int tokenIssued1 = token.getIssuedAt(); // Sets 5 minutes offset and assert access token will be still the same setAdapterAndServerTimeOffset(300, tokenMinTTLPage.toString()); tokenMinTTLPage.navigateTo(); token = tokenMinTTLPage.getAccessToken(); int tokenIssued2 = token.getIssuedAt(); Assert.assertEquals(tokenIssued1, tokenIssued2); assertFalse(token.isExpired()); // Sets 9 minutes offset and assert access token will be refreshed (accessTokenTimeout is 10 minutes, token-min-ttl is 2 minutes. Hence 8 minutes or more should be sufficient) setAdapterAndServerTimeOffset(540, tokenMinTTLPage.toString()); tokenMinTTLPage.navigateTo(); token = tokenMinTTLPage.getAccessToken(); int tokenIssued3 = token.getIssuedAt(); Assert.assertTrue(tokenIssued3 > tokenIssued1); // Revert times setAdapterAndServerTimeOffset(0, tokenMinTTLPage.toString()); } // Tests forwarding of parameters like "prompt" @Test public void testOIDCParamsForwarding() { // test login to customer-portal which does a bearer request to customer-db securePortal.navigateTo(); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); assertCurrentUrlEquals(securePortal); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); int currentTime = Time.currentTime(); setAdapterAndServerTimeOffset(10, securePortal.toString()); // Test I need to reauthenticate with prompt=login String appUri = tokenMinTTLPage.getUriBuilder().queryParam(OIDCLoginProtocol.PROMPT_PARAM, OIDCLoginProtocol.PROMPT_VALUE_LOGIN).build().toString(); URLUtils.navigateToUri(driver, appUri, true); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); testRealmLoginPage.form().login("bburke@redhat.com", "password"); AccessToken token = tokenMinTTLPage.getAccessToken(); int authTime = token.getAuthTime(); Assert.assertTrue(currentTime + 10 <= authTime); // Revert times setAdapterAndServerTimeOffset(0, tokenMinTTLPage.toString()); } @Test public void testBasicAuth() { String value = "hello"; Client client = ClientBuilder.newClient(); //pause(1000000); Response response = client.target(basicAuthPage .setTemplateValues("mposolda", "password", value).buildUri()).request().get(); assertThat(response, Matchers.statusCodeIs(Status.OK)); assertEquals(value, response.readEntity(String.class)); response.close(); response = client.target(basicAuthPage .setTemplateValues("invalid-user", "password", value).buildUri()).request().get(); assertThat(response, Matchers.statusCodeIs(Status.UNAUTHORIZED)); assertThat(response, Matchers.body(anyOf(containsString("Unauthorized"), containsString("Status 401")))); response = client.target(basicAuthPage .setTemplateValues("admin", "invalid-password", value).buildUri()).request().get(); assertThat(response, Matchers.statusCodeIs(Status.UNAUTHORIZED)); assertThat(response, Matchers.body(anyOf(containsString("Unauthorized"), containsString("Status 401")))); client.close(); } @Test public void grantServerBasedApp() { ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "customer-portal"); ClientRepresentation client = clientResource.toRepresentation(); client.setConsentRequired(true); clientResource.update(client); RealmRepresentation realm = testRealmResource().toRepresentation(); realm.setEventsEnabled(true); realm.setEnabledEventTypes(Arrays.asList("REVOKE_GRANT", "LOGIN")); realm.setEventsListeners(Arrays.asList("jboss-logging", "event-queue")); testRealmResource().update(realm); customerPortal.navigateTo(); loginPage.form().login("bburke@redhat.com", "password"); assertTrue(oAuthGrantPage.isCurrent()); oAuthGrantPage.accept(); String pageSource = driver.getPageSource(); waitForPageToLoad(driver); assertThat(pageSource, containsString("Bill Burke")); assertThat(pageSource, containsString("Stian Thorgersen")); String userId = ApiUtil.findUserByUsername(testRealmResource(), "bburke@redhat.com").getId(); assertEvents.expectLogin() .realm(realm.getId()) .client("customer-portal") .user(userId) .detail(Details.USERNAME, "bburke@redhat.com") .detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED) .detail(Details.REDIRECT_URI, customerPortal.getInjectedUrl().toString()) .removeDetail(Details.CODE_ID) .assertEvent(); assertEvents.expectCodeToToken(null, null) .realm(realm.getId()) .client("customer-portal") .user(userId) .session(AssertEvents.isUUID()) .removeDetail(Details.CODE_ID) .assertEvent(); applicationsPage.navigateTo(); applicationsPage.revokeGrantForApplication("customer-portal"); customerPortal.navigateTo(); assertTrue(oAuthGrantPage.isCurrent()); assertEvents.expect(EventType.REVOKE_GRANT) .realm(realm.getId()) .client("account") .user(userId) .detail(Details.REVOKED_CLIENT, "customer-portal") .assertEvent(); assertEvents.assertEmpty(); // Revert consent client = clientResource.toRepresentation(); client.setConsentRequired(false); clientResource.update(client); } @Test public void historyOfAccessResourceTest() throws IOException { RealmRepresentation realm = testRealmResource().toRepresentation(); realm.setEventsEnabled(true); realm.setEnabledEventTypes(Arrays.asList("LOGIN", "LOGIN_ERROR", "LOGOUT", "CODE_TO_TOKEN")); realm.setEventsListeners(Arrays.asList("jboss-logging", "event-queue")); testRealmResource().update(realm); customerPortal.navigateTo(); testRealmLoginPage.form().login("bburke@redhat.com", "password"); waitForPageToLoad(driver); String pageSource = driver.getPageSource(); assertThat(pageSource, containsString("Bill Burke")); assertThat(pageSource, containsString("Stian Thorgersen")); String userId = ApiUtil.findUserByUsername(testRealmResource(), "bburke@redhat.com").getId(); assertEvents.expectLogin() .realm(realm.getId()) .client("customer-portal") .user(userId) .detail(Details.USERNAME, "bburke@redhat.com") .detail(Details.CONSENT, Details.CONSENT_VALUE_NO_CONSENT_REQUIRED) .detail(Details.REDIRECT_URI, customerPortal.getInjectedUrl().toString()) .removeDetail(Details.CODE_ID) .assertEvent(); assertEvents.expectCodeToToken(null, null) .realm(realm.getId()) .client("customer-portal") .user(userId) .session(AssertEvents.isUUID()) .removeDetail(Details.CODE_ID) .assertEvent(); driver.navigate().to(testRealmPage.getOIDCLogoutUrl() + "?redirect_uri=" + customerPortal); assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); assertEvents.expectLogout(null) .realm(realm.getId()) .user(userId) .session(AssertEvents.isUUID()) .detail(Details.REDIRECT_URI, customerPortal.getInjectedUrl().toString()) .assertEvent(); assertEvents.assertEmpty(); String serverLogPath = null; String appServer = System.getProperty("app.server"); if (appServer != null && (appServer.equals("wildfly") || appServer.equals("eap6") || appServer.equals("eap"))) { serverLogPath = System.getProperty("app.server.home") + "/standalone/log/server.log"; } String appServerUrl; if (Boolean.parseBoolean(System.getProperty("app.server.ssl.required"))) { appServerUrl = "https://localhost:" + System.getProperty("app.server.https.port", "8543") + "/"; } else { appServerUrl = "http://localhost:" + System.getProperty("app.server.http.port", "8280") + "/"; } if (serverLogPath != null) { log.info("Checking app server log at: " + serverLogPath); File serverLog = new File(serverLogPath); String serverLogContent = FileUtils.readFileToString(serverLog); UserRepresentation bburke = ApiUtil.findUserByUsername(testRealmResource(), "bburke@redhat.com"); Pattern pattern = Pattern.compile("User '" + bburke.getId() + "' invoking '" + appServerUrl + "customer-portal[^\\s]+' on client 'customer-portal'"); Matcher matcher = pattern.matcher(serverLogContent); assertTrue(matcher.find()); assertTrue(serverLogContent.contains("User '" + bburke.getId() + "' invoking '" + appServerUrl + "customer-db/' on client 'customer-db'")); } else { log.info("Checking app server log on app-server: \"" + System.getProperty("app.server") + "\" is not supported."); } } @Test public void testWithoutKeycloakConf() { customerPortalNoConf.navigateTo(); String pageSource = driver.getPageSource(); assertTrue(pageSource.contains("Forbidden") || pageSource.contains("HTTP Status 401")); } }