/*
* 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.admin.authentication;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.keycloak.admin.client.resource.AuthenticationManagementResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;
import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
import org.keycloak.representations.idm.AuthenticationExecutionInfoRepresentation;
import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.util.AdminEventPaths;
import org.keycloak.testsuite.util.AssertAdminEvents;
import org.keycloak.testsuite.util.RealmBuilder;
import javax.ws.rs.core.Response;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/
public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
static final String REALM_NAME = "test";
static final String REQUIRED = "REQUIRED";
static final String OPTIONAL = "OPTIONAL";
static final String DISABLED = "DISABLED";
static final String ALTERNATIVE = "ALTERNATIVE";
RealmResource realmResource;
AuthenticationManagementResource authMgmtResource;
@Rule
public AssertAdminEvents assertAdminEvents = new AssertAdminEvents(this);
@Before
public void before() {
realmResource = adminClient.realms().realm(REALM_NAME);
authMgmtResource = realmResource.flows();
}
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation testRealmRep = RealmBuilder.create().name(REALM_NAME).testEventListener().build();
testRealmRep.setId(REALM_NAME);
testRealms.add(testRealmRep);
}
public static AuthenticationExecutionInfoRepresentation findExecutionByProvider(String provider, List<AuthenticationExecutionInfoRepresentation> executions) {
for (AuthenticationExecutionInfoRepresentation exec : executions) {
if (provider.equals(exec.getProviderId())) {
return exec;
}
}
return null;
}
AuthenticationFlowRepresentation findFlowByAlias(String alias, List<AuthenticationFlowRepresentation> flows) {
for (AuthenticationFlowRepresentation flow : flows) {
if (alias.equals(flow.getAlias())) {
return flow;
}
}
return null;
}
void compareExecution(AuthenticationExecutionInfoRepresentation expected, AuthenticationExecutionInfoRepresentation actual) {
Assert.assertEquals("Execution requirement - " + actual.getProviderId(), expected.getRequirement(), actual.getRequirement());
Assert.assertEquals("Execution display name - " + actual.getProviderId(), expected.getDisplayName(), actual.getDisplayName());
Assert.assertEquals("Execution configurable - " + actual.getProviderId(), expected.getConfigurable(), actual.getConfigurable());
Assert.assertEquals("Execution provider id - " + actual.getProviderId(), expected.getProviderId(), actual.getProviderId());
Assert.assertEquals("Execution level - " + actual.getProviderId(), expected.getLevel(), actual.getLevel());
Assert.assertEquals("Execution index - " + actual.getProviderId(), expected.getIndex(), actual.getIndex());
Assert.assertEquals("Execution authentication flow - " + actual.getProviderId(), expected.getAuthenticationFlow(), actual.getAuthenticationFlow());
Assert.assertEquals("Execution requirement choices - " + actual.getProviderId(), expected.getRequirementChoices(), actual.getRequirementChoices());
}
void compareExecution(AuthenticationExecutionExportRepresentation expected, AuthenticationExecutionExportRepresentation actual) {
Assert.assertEquals("Execution flowAlias - " + actual.getFlowAlias(), expected.getFlowAlias(), actual.getFlowAlias());
Assert.assertEquals("Execution authenticator - " + actual.getAuthenticator(), expected.getAuthenticator(), actual.getAuthenticator());
Assert.assertEquals("Execution userSetupAllowed - " + actual.getAuthenticator(), expected.isUserSetupAllowed(), actual.isUserSetupAllowed());
Assert.assertEquals("Execution authenticatorFlow - " + actual.getAuthenticator(), expected.isAutheticatorFlow(), actual.isAutheticatorFlow());
Assert.assertEquals("Execution authenticatorConfig - " + actual.getAuthenticator(), expected.getAuthenticatorConfig(), actual.getAuthenticatorConfig());
Assert.assertEquals("Execution priority - " + actual.getAuthenticator(), expected.getPriority(), actual.getPriority());
Assert.assertEquals("Execution requirement - " + actual.getAuthenticator(), expected.getRequirement(), actual.getRequirement());
}
void compareExecutions(List<AuthenticationExecutionExportRepresentation> expected, List<AuthenticationExecutionExportRepresentation> actual) {
Assert.assertNotNull("Executions should not be null", actual);
Assert.assertEquals("Size", expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++) {
compareExecution(expected.get(i), actual.get(i));
}
}
void compareFlows(AuthenticationFlowRepresentation expected, AuthenticationFlowRepresentation actual) {
Assert.assertEquals("Flow alias", expected.getAlias(), actual.getAlias());
Assert.assertEquals("Flow description", expected.getDescription(), actual.getDescription());
Assert.assertEquals("Flow providerId", expected.getProviderId(), actual.getProviderId());
Assert.assertEquals("Flow top level", expected.isTopLevel(), actual.isTopLevel());
Assert.assertEquals("Flow built-in", expected.isBuiltIn(), actual.isBuiltIn());
List<AuthenticationExecutionExportRepresentation> expectedExecs = expected.getAuthenticationExecutions();
List<AuthenticationExecutionExportRepresentation> actualExecs = actual.getAuthenticationExecutions();
if (expectedExecs == null) {
Assert.assertTrue("Executions should be null or empty", actualExecs == null || actualExecs.size() == 0);
} else {
compareExecutions(expectedExecs, actualExecs);
}
}
AuthenticationFlowRepresentation newFlow(String alias, String description,
String providerId, boolean topLevel, boolean builtIn) {
AuthenticationFlowRepresentation flow = new AuthenticationFlowRepresentation();
flow.setAlias(alias);
flow.setDescription(description);
flow.setProviderId(providerId);
flow.setTopLevel(topLevel);
flow.setBuiltIn(builtIn);
return flow;
}
AuthenticationExecutionInfoRepresentation newExecInfo(String displayName, String providerId, Boolean configurable,
int level, int index, String requirement, Boolean authFlow, String[] choices) {
AuthenticationExecutionInfoRepresentation execution = new AuthenticationExecutionInfoRepresentation();
execution.setRequirement(requirement);
execution.setDisplayName(displayName);
execution.setConfigurable(configurable);
execution.setProviderId(providerId);
execution.setLevel(level);
execution.setIndex(index);
execution.setAuthenticationFlow(authFlow);
if (choices != null) {
execution.setRequirementChoices(Arrays.asList(choices));
}
return execution;
}
void addExecInfo(List<AuthenticationExecutionInfoRepresentation> target, String displayName, String providerId, Boolean configurable,
int level, int index, String requirement, Boolean authFlow, String[] choices) {
AuthenticationExecutionInfoRepresentation exec = newExecInfo(displayName, providerId, configurable, level, index, requirement, authFlow, choices);
target.add(exec);
}
AuthenticatorConfigRepresentation newConfig(String alias, String[] keyvalues) {
AuthenticatorConfigRepresentation config = new AuthenticatorConfigRepresentation();
config.setAlias(alias);
if (keyvalues == null) {
throw new IllegalArgumentException("keyvalues == null");
}
if (keyvalues.length % 2 != 0) {
throw new IllegalArgumentException("keyvalues should have even number of elements");
}
LinkedHashMap<String, String> params = new LinkedHashMap<>();
for (int i = 0; i < keyvalues.length; i += 2) {
params.put(keyvalues[i], keyvalues[i + 1]);
}
config.setConfig(params);
return config;
}
void createFlow(AuthenticationFlowRepresentation flowRep) {
Response response = authMgmtResource.createFlow(flowRep);
org.keycloak.testsuite.Assert.assertEquals(201, response.getStatus());
response.close();
String flowId = ApiUtil.getCreatedId(response);
getCleanup().addAuthenticationFlowId(flowId);
assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AssertAdminEvents.isExpectedPrefixFollowedByUuid(AdminEventPaths.authFlowsPath()), flowRep, ResourceType.AUTH_FLOW);
}
}