/*
* 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.example.authorization;
import org.jboss.arquillian.container.test.api.Deployer;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.graphene.page.Page;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.keycloak.admin.client.resource.AuthorizationResource;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ClientsResource;
import org.keycloak.admin.client.resource.ResourcesResource;
import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
import org.keycloak.testsuite.ProfileAssume;
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
import org.keycloak.testsuite.adapter.page.PhotozClientAuthzTestApp;
import org.keycloak.util.JsonSerialization;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.keycloak.testsuite.util.IOUtil.loadJson;
import static org.keycloak.testsuite.util.IOUtil.loadRealm;
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAdapterTest {
private static final String REALM_NAME = "photoz";
private static final String RESOURCE_SERVER_ID = "photoz-restful-api";
private static int TOKEN_LIFESPAN_LEEWAY = 3; // seconds
@ArquillianResource
private Deployer deployer;
@Page
private PhotozClientAuthzTestApp clientPage;
@Override
public void setDefaultPageUriParameters() {
super.setDefaultPageUriParameters();
testRealmPage.setAuthRealm(REALM_NAME);
}
@BeforeClass
public static void enabled() { ProfileAssume.assumePreview(); }
@Before
public void beforePhotozExampleAdapterTest() throws FileNotFoundException {
deleteAllCookiesForClientPage();
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Only Owner Policy".equals(policy.getName())) {
policy.getConfig().put("mavenArtifactVersion", System.getProperty("project.version"));
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
}
@Override
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation realm = loadRealm(new File(TEST_APPS_HOME_DIR + "/photoz/photoz-realm.json"));
realm.setAccessTokenLifespan(30 + TOKEN_LIFESPAN_LEEWAY); // seconds
testRealms.add(realm);
}
@Deployment(name = PhotozClientAuthzTestApp.DEPLOYMENT_NAME)
public static WebArchive deploymentClient() throws IOException {
return exampleDeployment(PhotozClientAuthzTestApp.DEPLOYMENT_NAME);
}
@Deployment(name = RESOURCE_SERVER_ID, managed = false, testable = false)
public static WebArchive deploymentResourceServer() throws IOException {
return exampleDeployment(RESOURCE_SERVER_ID);
}
@Override
public void beforeAbstractKeycloakTest() throws Exception {
super.beforeAbstractKeycloakTest();
importResourceServerSettings();
}
@Test
public void testUserCanCreateAndDeleteAlbum() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
this.clientPage.createAlbum("Alice Family Album");
List<ResourceRepresentation> resources = getAuthorizationResource().resources().resources();
assertFalse(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
this.clientPage.deleteAlbum("Alice Family Album");
resources = getAuthorizationResource().resources().resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void createAlbumWithInvalidUser() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
clientPage.createAlbumWithInvalidUser("Alice Family Album");
waitUntilElement(clientPage.getOutput()).text().not().contains("Request was successful");
waitUntilElement(clientPage.getOutput()).text().contains("Could not register protected resource");
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testOnlyOwnerCanDeleteAlbum() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
this.clientPage.createAlbum("Alice-Family-Album");
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
List<ResourceRepresentation> resources = getAuthorizationResource().resources().resources();
assertFalse(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Delete Album Permission".equals(policy.getName())) {
policy.getConfig().put("applyPolicies", "[\"Only Owner Policy\"]");
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum("Alice-Family-Album");
assertTrue(this.clientPage.wasDenied());
resources = getAuthorizationResource().resources().resources();
assertFalse(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Delete Album Permission".equals(policy.getName())) {
policy.getConfig().put("applyPolicies", "[\"Only Owner and Administrators Policy\"]");
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum("Alice-Family-Album");
assertFalse(this.clientPage.wasDenied());
resources = getAuthorizationResource().resources().resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testRegularUserCanNotAccessAdminResources() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
this.clientPage.navigateToAdminAlbum();
assertTrue(this.clientPage.wasDenied());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testAdminOnlyFromSpecificAddress() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
assertFalse(this.clientPage.wasDenied());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Only From a Specific Client Address".equals(policy.getName())) {
String code = policy.getConfig().get("code");
policy.getConfig().put("code", code.replaceAll("127.0.0.1", "127.3.3.3"));
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
this.clientPage.navigateToAdminAlbum();
assertTrue(this.clientPage.wasDenied());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testAdminWithoutPermissionsToTypedResource() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
this.clientPage.createAlbum("Alice Family Album");
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
assertFalse(this.clientPage.wasDenied());
this.clientPage.viewAlbum("Alice Family Album");
assertFalse(this.clientPage.wasDenied());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Album Resource Permission".equals(policy.getName())) {
policy.getConfig().put("applyPolicies", "[\"Any User Policy\"]");
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
if ("Any User Policy".equals(policy.getName())) {
ClientResource resourceServerClient = getClientResource(RESOURCE_SERVER_ID);
RoleResource manageAlbumRole = resourceServerClient.roles().get("manage-albums");
RoleRepresentation roleRepresentation = manageAlbumRole.toRepresentation();
List<Map> roles = JsonSerialization.readValue(policy.getConfig().get("roles"), List.class);
roles = roles.stream().filter(new Predicate<Map>() {
@Override
public boolean test(Map map) {
return !map.get("id").equals(roleRepresentation.getId());
}
}).collect(Collectors.toList());
policy.getConfig().put("roles", JsonSerialization.writeValueAsString(roles));
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum("Alice Family Album");
assertTrue(this.clientPage.wasDenied());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Album Resource Permission".equals(policy.getName())) {
policy.getConfig().put("applyPolicies", "[\"Any User Policy\", \"Administration Policy\"]");
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum("Alice Family Album");
assertFalse(this.clientPage.wasDenied());
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum("Alice Family Album");
List<ResourceRepresentation> resources = getAuthorizationResource().resources().resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testAdminWithoutPermissionsToDeleteAlbum() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
this.clientPage.createAlbum("Alice Family Album");
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
assertFalse(this.clientPage.wasDenied());
this.clientPage.deleteAlbum("Alice Family Album");
assertFalse(this.clientPage.wasDenied());
List<ResourceRepresentation> resources = getAuthorizationResource().resources().resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Delete Album Permission".equals(policy.getName())) {
policy.getConfig().put("applyPolicies", "[\"Only Owner Policy\"]");
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
loginToClientPage("alice", "alice");
this.clientPage.createAlbum("Alice Family Album");
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum("Alice Family Album");
assertFalse(this.clientPage.wasDenied());
resources = getAuthorizationResource().resources().resources();
assertFalse(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum("Alice Family Album");
assertTrue(this.clientPage.wasDenied());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Delete Album Permission".equals(policy.getName())) {
policy.getConfig().put("applyPolicies", "[\"Only Owner and Administrators Policy\"]");
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum("Alice Family Album");
assertFalse(this.clientPage.wasDenied());
resources = getAuthorizationResource().resources().resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testClientRoleRepresentingUserConsent() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
assertFalse(this.clientPage.wasDenied());
UsersResource usersResource = realmsResouce().realm(REALM_NAME).users();
List<UserRepresentation> users = usersResource.search("alice", null, null, null, null, null);
assertFalse(users.isEmpty());
UserRepresentation userRepresentation = users.get(0);
UserResource userResource = usersResource.get(userRepresentation.getId());
ClientResource html5ClientApp = getClientResource("photoz-html5-client");
userResource.revokeConsent(html5ClientApp.toRepresentation().getClientId());
ClientResource resourceServerClient = getClientResource(RESOURCE_SERVER_ID);
RoleResource roleResource = resourceServerClient.roles().get("manage-albums");
RoleRepresentation roleRepresentation = roleResource.toRepresentation();
roleRepresentation.setScopeParamRequired(true);
roleResource.update(roleRepresentation);
loginToClientPage("alice", "alice");
assertTrue(this.clientPage.wasDenied());
loginToClientPage("alice", "alice", RESOURCE_SERVER_ID + "/manage-albums");
assertFalse(this.clientPage.wasDenied());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testClientRoleNotRequired() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
assertFalse(this.clientPage.wasDenied());
UsersResource usersResource = realmsResouce().realm(REALM_NAME).users();
List<UserRepresentation> users = usersResource.search("alice", null, null, null, null, null);
assertFalse(users.isEmpty());
UserRepresentation userRepresentation = users.get(0);
UserResource userResource = usersResource.get(userRepresentation.getId());
ClientResource html5ClientApp = getClientResource("photoz-html5-client");
userResource.revokeConsent(html5ClientApp.toRepresentation().getClientId());
ClientResource resourceServerClient = getClientResource(RESOURCE_SERVER_ID);
RoleResource manageAlbumRole = resourceServerClient.roles().get("manage-albums");
RoleRepresentation roleRepresentation = manageAlbumRole.toRepresentation();
roleRepresentation.setScopeParamRequired(true);
manageAlbumRole.update(roleRepresentation);
loginToClientPage("alice", "alice");
assertTrue(this.clientPage.wasDenied());
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
if ("Any User Policy".equals(policy.getName())) {
List<Map> roles = JsonSerialization.readValue(policy.getConfig().get("roles"), List.class);
roles.forEach(role -> {
String roleId = (String) role.get("id");
if (roleId.equals(manageAlbumRole.toRepresentation().getId())) {
role.put("required", false);
}
});
policy.getConfig().put("roles", JsonSerialization.writeValueAsString(roles));
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
}
}
loginToClientPage("alice", "alice");
assertFalse(this.clientPage.wasDenied());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testOverridePermissionFromResourceParent() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
String resourceName = "My Resource Instance";
this.clientPage.createAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.viewAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.navigateTo();
this.clientPage.deleteAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.createAlbum(resourceName);
this.clientPage.logOut();
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.navigateToAdminAlbum();;
this.clientPage.deleteAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
loginToClientPage("alice", "alice");
this.clientPage.createAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
getAuthorizationResource().resources().resources().forEach(resource -> {
if (resource.getName().equals(resourceName)) {
try {
PolicyRepresentation resourceInstancePermission = new PolicyRepresentation();
resourceInstancePermission.setName(resourceName + "Permission");
resourceInstancePermission.setType("resource");
Map<String, String> config = new HashMap<>();
config.put("resources", JsonSerialization.writeValueAsString(Arrays.asList(resource.getId())));
config.put("applyPolicies", JsonSerialization.writeValueAsString(Arrays.asList("Only Owner Policy")));
resourceInstancePermission.setConfig(config);
getAuthorizationResource().policies().create(resourceInstancePermission);
} catch (Exception e) {
throw new RuntimeException("Error creating policy.", e);
}
}
});
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum(resourceName);
assertTrue(this.clientPage.wasDenied());
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum(resourceName);
assertTrue(this.clientPage.wasDenied());
loginToClientPage("alice", "alice");
this.clientPage.deleteAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
ResourcesResource resourcesResource = getAuthorizationResource().resources();
List<ResourceRepresentation> resources = resourcesResource.resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
@Test
public void testInheritPermissionFromResourceParent() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
loginToClientPage("alice", "alice");
String resourceName = "My Resource Instance";
this.clientPage.createAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.viewAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.navigateTo();
this.clientPage.deleteAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.createAlbum(resourceName);
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.navigateToAdminAlbum();;
this.clientPage.deleteAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
loginToClientPage("alice", "alice");
this.clientPage.createAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
ResourcesResource resourcesResource = getAuthorizationResource().resources();
resourcesResource.resources().forEach(resource -> {
if (resource.getName().equals(resourceName)) {
try {
PolicyRepresentation resourceInstancePermission = new PolicyRepresentation();
resourceInstancePermission.setName(resourceName + "Permission");
resourceInstancePermission.setType("resource");
Map<String, String> config = new HashMap<>();
config.put("resources", JsonSerialization.writeValueAsString(Arrays.asList(resource.getId())));
config.put("applyPolicies", JsonSerialization.writeValueAsString(Arrays.asList("Only Owner Policy")));
resourceInstancePermission.setConfig(config);
getAuthorizationResource().policies().create(resourceInstancePermission);
} catch (Exception e) {
throw new RuntimeException("Error creating policy.", e);
}
}
});
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum(resourceName);
assertTrue(this.clientPage.wasDenied());
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum(resourceName);
assertTrue(this.clientPage.wasDenied());
resourcesResource.resources().forEach(resource -> {
if (resource.getName().equals(resourceName)) {
resource.setScopes(resource.getScopes().stream().filter(scope -> !scope.getName().equals("urn:photoz.com:scopes:album:view")).collect(Collectors.toSet()));
resourcesResource.resource(resource.getId()).update(resource);
}
});
loginToClientPage("admin", "admin");
this.clientPage.navigateToAdminAlbum();
this.clientPage.viewAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
this.clientPage.navigateToAdminAlbum();
this.clientPage.deleteAlbum(resourceName);
assertTrue(this.clientPage.wasDenied());
loginToClientPage("alice", "alice");
this.clientPage.deleteAlbum(resourceName);
assertFalse(this.clientPage.wasDenied());
List<ResourceRepresentation> resources = resourcesResource.resources();
assertTrue(resources.stream().filter(resource -> resource.getOwner().getName().equals("alice")).collect(Collectors.toList()).isEmpty());
resourcesResource.resources().forEach(resource -> {
if (resource.getName().equals(resourceName)) {
resource.setScopes(Collections.emptySet());
resourcesResource.resource(resource.getId()).update(resource);
}
});
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
//KEYCLOAK-3777
@Test
public void testEntitlementRequest() throws Exception {
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
clientPage.navigateTo();
loginToClientPage("admin", "admin");
clientPage.requestEntitlements();
assertTrue(driver.getPageSource().contains("urn:photoz.com:scopes:album:admin:manage"));
clientPage.requestEntitlement();
String pageSource = driver.getPageSource();
assertTrue(pageSource.contains("urn:photoz.com:scopes:album:view"));
assertFalse(pageSource.contains("urn:photoz.com:scopes:album:admin:manage"));
} finally {
this.deployer.undeploy(RESOURCE_SERVER_ID);
}
}
private void importResourceServerSettings() throws FileNotFoundException {
getAuthorizationResource().importSettings(loadJson(new FileInputStream(new File(TEST_APPS_HOME_DIR + "/photoz/photoz-restful-api-authz-service.json")), ResourceServerRepresentation.class));
}
private AuthorizationResource getAuthorizationResource() throws FileNotFoundException {
return getClientResource(RESOURCE_SERVER_ID).authorization();
}
private ClientResource getClientResource(String clientId) {
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
return clients.get(resourceServer.getId());
}
private void deleteAllCookiesForClientPage() {
driver.manage().deleteAllCookies();
}
private void loginToClientPage(String username, String password, String... scopes) throws InterruptedException {
// We need to log out by deleting cookies because the log out button sometimes doesn't work in PhantomJS
deleteAllCookiesForTestRealm();
clientPage.navigateTo();
clientPage.login(username, password, scopes);
}
}