/*
* 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.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.drone.api.annotation.Drone;
import org.jboss.arquillian.graphene.page.Page;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.After;
import org.junit.Test;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
import org.keycloak.testsuite.adapter.page.SessionPortal;
import org.keycloak.testsuite.auth.page.account.Sessions;
import org.keycloak.testsuite.auth.page.login.Login;
import org.keycloak.testsuite.util.SecondBrowser;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
/**
*
* @author tkyjovsk
*/
public abstract class AbstractSessionServletAdapterTest extends AbstractServletsAdapterTest {
@Page
private SessionPortal sessionPortalPage;
@Page
private Sessions testRealmSessions;
@Override
public void setDefaultPageUriParameters() {
super.setDefaultPageUriParameters();
testRealmSessions.setAuthRealm(DEMO);
}
@Deployment(name = SessionPortal.DEPLOYMENT_NAME)
protected static WebArchive sessionPortal() {
return servletDeployment(SessionPortal.DEPLOYMENT_NAME, "keycloak.json", SessionServlet.class);
}
@After
public void afterSessionServletAdapterTest() {
sessionPortalPage.navigateTo();
driver.manage().deleteAllCookies();
}
@Drone
@SecondBrowser
protected WebDriver driver2;
@Test
public void testSingleSessionInvalidated() {
loginAndCheckSession(driver, testRealmLoginPage);
// cannot pass to loginAndCheckSession becayse loginPage is not working together with driver2, therefore copypasta
driver2.navigate().to(sessionPortalPage.toString());
assertCurrentUrlStartsWithLoginUrlOf(driver2, testRealmPage);
driver2.findElement(By.id("username")).sendKeys("bburke@redhat.com");
driver2.findElement(By.id("password")).sendKeys("password");
driver2.findElement(By.id("password")).submit();
assertCurrentUrlEquals(driver2, sessionPortalPage);
String pageSource = driver2.getPageSource();
assertTrue(pageSource.contains("Counter=1"));
// Counter increased now
driver2.navigate().to(sessionPortalPage.toString());
pageSource = driver2.getPageSource();
assertTrue(pageSource.contains("Counter=2"));
// Logout in browser1
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
.queryParam(OAuth2Constants.REDIRECT_URI, sessionPortalPage.toString()).build("demo").toString();
driver.navigate().to(logoutUri);
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
// Assert that I am logged out in browser1
sessionPortalPage.navigateTo();
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
// Assert that I am still logged in browser2 and same session is still preserved
driver2.navigate().to(sessionPortalPage.toString());
assertCurrentUrlEquals(driver2, sessionPortalPage);
pageSource = driver2.getPageSource();
assertTrue(pageSource.contains("Counter=3"));
driver2.navigate().to(logoutUri);
assertCurrentUrlStartsWithLoginUrlOf(driver2, testRealmPage);
}
@Test
public void testSessionInvalidatedAfterFailedRefresh() {
RealmRepresentation testRealmRep = testRealmResource().toRepresentation();
ClientResource sessionPortalRes = null;
for (ClientRepresentation clientRep : testRealmResource().clients().findAll()) {
if ("session-portal".equals(clientRep.getClientId())) {
sessionPortalRes = testRealmResource().clients().get(clientRep.getId());
}
}
assertNotNull(sessionPortalRes);
sessionPortalRes.toRepresentation().setAdminUrl("");
int origTokenLifespan = testRealmRep.getAccessCodeLifespan();
testRealmRep.setAccessCodeLifespan(1);
testRealmResource().update(testRealmRep);
// Login
loginAndCheckSession(driver, testRealmLoginPage);
// Logout
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
.queryParam(OAuth2Constants.REDIRECT_URI, sessionPortalPage.toString()).build("demo").toString();
driver.navigate().to(logoutUri);
// Assert that http session was invalidated
sessionPortalPage.navigateTo();
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
testRealmLoginPage.form().login("bburke@redhat.com", "password");
assertCurrentUrlEquals(sessionPortalPage);
String pageSource = driver.getPageSource();
assertTrue(pageSource.contains("Counter=1"));
sessionPortalRes.toRepresentation().setAdminUrl(sessionPortalPage.toString());
testRealmRep.setAccessCodeLifespan(origTokenLifespan);
testRealmResource().update(testRealmRep);
}
@Test
public void testAdminApplicationLogout() {
// login as bburke
loginAndCheckSession(driver, testRealmLoginPage);
// logout mposolda with admin client
UserRepresentation mposolda = testRealmResource().users().search("mposolda", null, null, null, null, null).get(0);
testRealmResource().users().get(mposolda.getId()).logout();
// bburke should be still logged with original httpSession in our browser window
sessionPortalPage.navigateTo();
assertCurrentUrlEquals(sessionPortalPage);
String pageSource = driver.getPageSource();
assertTrue(pageSource.contains("Counter=3"));
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
.queryParam(OAuth2Constants.REDIRECT_URI, sessionPortalPage.toString()).build("demo").toString();
driver.navigate().to(logoutUri);
}
@Test
public void testAccountManagementSessionsLogout() {
// login as bburke
loginAndCheckSession(driver, testRealmLoginPage);
testRealmSessions.navigateTo();
testRealmSessions.logoutAll();
// Assert I need to login again (logout was propagated to the app)
loginAndCheckSession(driver, testRealmLoginPage);
}
private void loginAndCheckSession(WebDriver driver, Login login) {
sessionPortalPage.navigateTo();
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
login.form().login("bburke@redhat.com", "password");
assertCurrentUrlEquals(sessionPortalPage);
String pageSource = driver.getPageSource();
assertTrue(pageSource.contains("Counter=1"));
// Counter increased now
sessionPortalPage.navigateTo();
pageSource = driver.getPageSource();
assertTrue(pageSource.contains("Counter=2"));
}
}