Allow setting authentication flow execution priority value via Admin API
Closes #20747 Signed-off-by: Andrejs Mivreniks <andrejs@fastmail.com>
This commit is contained in:
parent
3f49036192
commit
1cf87407fe
20 changed files with 216 additions and 98 deletions
|
@ -28,7 +28,7 @@ public class AbstractAuthenticationExecutionRepresentation implements Serializab
|
|||
private String authenticator;
|
||||
private boolean authenticatorFlow;
|
||||
private String requirement;
|
||||
private int priority;
|
||||
private Integer priority;
|
||||
|
||||
public String getAuthenticatorConfig() {
|
||||
return authenticatorConfig;
|
||||
|
@ -54,11 +54,11 @@ public class AbstractAuthenticationExecutionRepresentation implements Serializab
|
|||
this.requirement = requirement;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
public Integer getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
public void setPriority(Integer priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ public class AuthenticationExecutionInfoRepresentation implements Serializable {
|
|||
protected String flowId;
|
||||
protected int level;
|
||||
protected int index;
|
||||
protected int priority;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
|
@ -143,4 +144,12 @@ public class AuthenticationExecutionInfoRepresentation implements Serializable {
|
|||
public void setFlowId(String flowId) {
|
||||
this.flowId = flowId;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ public interface AuthenticationManagementResource {
|
|||
@Path("/flows/{flowAlias}/copy")
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Response copy(@PathParam("flowAlias") String flowAlias, Map<String, String> data);
|
||||
Response copy(@PathParam("flowAlias") String flowAlias, Map<String, Object> data);
|
||||
|
||||
@Path("/flows/{id}")
|
||||
@PUT
|
||||
|
@ -98,12 +98,12 @@ public interface AuthenticationManagementResource {
|
|||
@Path("/flows/{flowAlias}/executions/flow")
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, String> data);
|
||||
void addExecutionFlow(@PathParam("flowAlias") String flowAlias, Map<String, Object> data);
|
||||
|
||||
@Path("/flows/{flowAlias}/executions/execution")
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
void addExecution(@PathParam("flowAlias") String flowAlias, Map<String, String> data);
|
||||
void addExecution(@PathParam("flowAlias") String flowAlias, Map<String, Object> data);
|
||||
|
||||
@Path("/flows/{flowAlias}/executions")
|
||||
@GET
|
||||
|
|
|
@ -1416,7 +1416,9 @@ public class DefaultExportImportManager implements ExportImportManager {
|
|||
AuthenticationFlowModel flow = realm.getFlowByAlias(rep.getFlowAlias());
|
||||
model.setFlowId(flow.getId());
|
||||
}
|
||||
model.setPriority(rep.getPriority());
|
||||
if (rep.getPriority() != null) {
|
||||
model.setPriority(rep.getPriority());
|
||||
}
|
||||
try {
|
||||
model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
|
||||
model.setParentFlow(parentFlow.getId());
|
||||
|
|
|
@ -635,7 +635,7 @@ public class RepresentationToModel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void updateClientScopes(ClientRepresentation resourceRep, ClientModel client) {
|
||||
if (resourceRep.getDefaultClientScopes() != null || resourceRep.getOptionalClientScopes() != null) {
|
||||
// First remove all default/built in client scopes
|
||||
|
@ -859,16 +859,16 @@ public class RepresentationToModel {
|
|||
public static IdentityProviderModel toModel(RealmModel realm, IdentityProviderRepresentation representation, KeycloakSession session) {
|
||||
IdentityProviderFactory providerFactory = (IdentityProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(
|
||||
IdentityProvider.class, representation.getProviderId());
|
||||
|
||||
|
||||
if (providerFactory == null) {
|
||||
providerFactory = (IdentityProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(
|
||||
SocialIdentityProvider.class, representation.getProviderId());
|
||||
}
|
||||
|
||||
|
||||
if (providerFactory == null) {
|
||||
throw new IllegalArgumentException("Invalid identity provider id [" + representation.getProviderId() + "]");
|
||||
}
|
||||
|
||||
|
||||
IdentityProviderModel identityProviderModel = providerFactory.createConfig();
|
||||
|
||||
identityProviderModel.setInternalId(representation.getInternalId());
|
||||
|
@ -984,7 +984,9 @@ public class RepresentationToModel {
|
|||
model.setFlowId(rep.getFlowId());
|
||||
|
||||
model.setAuthenticator(rep.getAuthenticator());
|
||||
model.setPriority(rep.getPriority());
|
||||
if (rep.getPriority() != null) {
|
||||
model.setPriority(rep.getPriority());
|
||||
}
|
||||
model.setParentFlow(rep.getParentFlow());
|
||||
model.setAuthenticatorFlow(rep.isAuthenticatorFlow());
|
||||
model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
|
||||
|
|
|
@ -471,7 +471,7 @@ public class AuthenticationManagementResource {
|
|||
* Add new flow with new execution to existing flow
|
||||
*
|
||||
* @param flowAlias Alias of parent authentication flow
|
||||
* @param data New authentication flow / execution JSON data containing 'alias', 'type', 'provider', and 'description' attributes
|
||||
* @param data New authentication flow / execution JSON data containing 'alias', 'type', 'provider', 'priority', and 'description' attributes
|
||||
*/
|
||||
@Path("/flows/{flowAlias}/executions/flow")
|
||||
@POST
|
||||
|
@ -479,7 +479,7 @@ public class AuthenticationManagementResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Tag(name = KeycloakOpenAPI.Admin.Tags.AUTHENTICATION_MANAGEMENT)
|
||||
@Operation( summary = "Add new flow with new execution to existing flow")
|
||||
public Response addExecutionFlow(@Parameter(description = "Alias of parent authentication flow") @PathParam("flowAlias") String flowAlias, @Parameter(description = "New authentication flow / execution JSON data containing 'alias', 'type', 'provider', and 'description' attributes") Map<String, String> data) {
|
||||
public Response addExecutionFlow(@Parameter(description = "Alias of parent authentication flow") @PathParam("flowAlias") String flowAlias, @Parameter(description = "New authentication flow / execution JSON data containing 'alias', 'type', 'provider', 'priority', and 'description' attributes") Map<String, Object> data) {
|
||||
auth.realm().requireManageRealm();
|
||||
|
||||
AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
|
||||
|
@ -489,12 +489,13 @@ public class AuthenticationManagementResource {
|
|||
if (parentFlow.isBuiltIn()) {
|
||||
throw new BadRequestException("It is illegal to add sub-flow to a built in flow");
|
||||
}
|
||||
String alias = data.get("alias");
|
||||
String type = data.get("type");
|
||||
String provider = data.get("provider");
|
||||
String alias = (String) data.get("alias");
|
||||
String type = (String) data.get("type");
|
||||
String provider = (String) data.get("provider");
|
||||
int priority = data.containsKey("priority") ? (Integer) data.get("priority") : getNextPriority(parentFlow);
|
||||
|
||||
//Make sure that the description to avoid NullPointerException
|
||||
String description = Objects.isNull(data.get("description")) ? "" : data.get("description");
|
||||
String description = Objects.isNull(data.get("description")) ? "" : (String) data.get("description");
|
||||
|
||||
|
||||
AuthenticationFlowModel newFlow = realm.getFlowByAlias(alias);
|
||||
|
@ -514,7 +515,7 @@ public class AuthenticationManagementResource {
|
|||
if (type.equals("form-flow")) {
|
||||
execution.setAuthenticator(provider);
|
||||
}
|
||||
execution.setPriority(getNextPriority(parentFlow));
|
||||
execution.setPriority(priority);
|
||||
execution = realm.addAuthenticatorExecution(execution);
|
||||
|
||||
data.put("id", execution.getId());
|
||||
|
@ -534,7 +535,7 @@ public class AuthenticationManagementResource {
|
|||
* Add new authentication execution to a flow
|
||||
*
|
||||
* @param flowAlias Alias of parent flow
|
||||
* @param data New execution JSON data containing 'provider' attribute
|
||||
* @param data New execution JSON data containing 'provider' and 'priority' (optional) attribute
|
||||
*/
|
||||
@Path("/flows/{flowAlias}/executions/execution")
|
||||
@POST
|
||||
|
@ -542,7 +543,7 @@ public class AuthenticationManagementResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Tag(name = KeycloakOpenAPI.Admin.Tags.AUTHENTICATION_MANAGEMENT)
|
||||
@Operation( summary="Add new authentication execution to a flow")
|
||||
public Response addExecutionToFlow(@Parameter(description = "Alias of parent flow") @PathParam("flowAlias") String flowAlias, @Parameter(description = "New execution JSON data containing 'provider' attribute") Map<String, String> data) {
|
||||
public Response addExecutionToFlow(@Parameter(description = "Alias of parent flow") @PathParam("flowAlias") String flowAlias, @Parameter(description = "New execution JSON data containing 'provider' and 'priority' (optional) attribute") Map<String, Object> data) {
|
||||
auth.realm().requireManageRealm();
|
||||
|
||||
AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
|
||||
|
@ -552,7 +553,8 @@ public class AuthenticationManagementResource {
|
|||
if (parentFlow.isBuiltIn()) {
|
||||
throw new BadRequestException("It is illegal to add execution to a built in flow");
|
||||
}
|
||||
String provider = data.get("provider");
|
||||
String provider = (String) data.get("provider");
|
||||
int priority = data.containsKey("priority") ? (Integer) data.get("priority") : getNextPriority(parentFlow);
|
||||
|
||||
// make sure provider is one of the registered providers
|
||||
ProviderFactory f = getProviderFactory( parentFlow, provider);
|
||||
|
@ -568,7 +570,7 @@ public class AuthenticationManagementResource {
|
|||
|
||||
execution.setAuthenticatorFlow(false);
|
||||
execution.setAuthenticator(provider);
|
||||
execution.setPriority(getNextPriority(parentFlow));
|
||||
execution.setPriority(priority);
|
||||
|
||||
execution = realm.addAuthenticatorExecution(execution);
|
||||
|
||||
|
@ -647,6 +649,7 @@ public class AuthenticationManagementResource {
|
|||
rep.setLevel(level);
|
||||
rep.setIndex(index.getAndIncrement());
|
||||
rep.setRequirementChoices(new LinkedList<>());
|
||||
rep.setPriority(execution.getPriority());
|
||||
if (execution.isAuthenticatorFlow()) {
|
||||
AuthenticationFlowModel flowRef = realm.getAuthenticationFlowById(execution.getFlowId());
|
||||
if (AuthenticationFlow.BASIC_FLOW.equals(flowRef.getProviderId())) {
|
||||
|
@ -741,8 +744,16 @@ public class AuthenticationManagementResource {
|
|||
throw new NotFoundException("Illegal execution");
|
||||
|
||||
}
|
||||
boolean updateExecution = false;
|
||||
if (model.getPriority() != rep.getPriority()) {
|
||||
model.setPriority(rep.getPriority());
|
||||
updateExecution = true;
|
||||
}
|
||||
if (!model.getRequirement().name().equals(rep.getRequirement())) {
|
||||
model.setRequirement(AuthenticationExecutionModel.Requirement.valueOf(rep.getRequirement()));
|
||||
updateExecution = true;
|
||||
}
|
||||
if (updateExecution) {
|
||||
realm.updateAuthenticatorExecution(model);
|
||||
adminEvent.operation(OperationType.UPDATE).resource(ResourceType.AUTH_EXECUTION).resourcePath(session.getContext().getUri()).representation(rep).success();
|
||||
return Response.accepted(flow).build();
|
||||
|
@ -825,7 +836,8 @@ public class AuthenticationManagementResource {
|
|||
if (parentFlow.isBuiltIn()) {
|
||||
throw new BadRequestException("It is illegal to add execution to a built in flow");
|
||||
}
|
||||
model.setPriority(getNextPriority(parentFlow));
|
||||
int priority = execution.getPriority() != null ? execution.getPriority() : getNextPriority(parentFlow);
|
||||
model.setPriority(priority);
|
||||
model = realm.addAuthenticatorExecution(model);
|
||||
|
||||
if (!execution.isAuthenticatorFlow()) {
|
||||
|
|
|
@ -178,7 +178,7 @@ public class Creator<T> implements AutoCloseable {
|
|||
}
|
||||
|
||||
public AuthenticationExecutionInfoRepresentation addExecution(String providerId) {
|
||||
Map<String, String> c = new HashMap<>();
|
||||
Map<String, Object> c = new HashMap<>();
|
||||
c.put("provider", providerId);
|
||||
resource().addExecution(alias, c); // addExecution only handles "provider" in data
|
||||
return resource().getExecutions(alias).stream()
|
||||
|
|
|
@ -1054,7 +1054,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
|
|||
}
|
||||
|
||||
private void configureBrowserFlowWithWebAuthnAuthenticator(String newFlowAlias) {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", newFlowAlias);
|
||||
Response response = testRealm().flows().copy("browser", params);
|
||||
response.close();
|
||||
|
|
|
@ -531,7 +531,7 @@ public class CustomAuthFlowOTPTest extends AbstractCustomAccountManagementTest {
|
|||
response.close();
|
||||
|
||||
//add execution - username-password form
|
||||
Map<String, String> data = new HashMap<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("provider", "auth-username-password-form");
|
||||
getAuthMgmtResource().addExecution(flowAlias, data);
|
||||
|
||||
|
|
|
@ -1137,17 +1137,17 @@ public class PermissionsTest extends AbstractKeycloakTest {
|
|||
}, Resource.REALM, true);
|
||||
invoke(new InvocationWithResponse() {
|
||||
public void invoke(RealmResource realm, AtomicReference<Response> response) {
|
||||
response.set(realm.flows().copy("nosuch", Collections.<String, String>emptyMap()));
|
||||
response.set(realm.flows().copy("nosuch", Collections.<String, Object>emptyMap()));
|
||||
}
|
||||
}, Resource.REALM, true);
|
||||
invoke(new Invocation() {
|
||||
public void invoke(RealmResource realm) {
|
||||
realm.flows().addExecutionFlow("nosuch", Collections.<String, String>emptyMap());
|
||||
realm.flows().addExecutionFlow("nosuch", Collections.<String, Object>emptyMap());
|
||||
}
|
||||
}, Resource.REALM, true);
|
||||
invoke(new Invocation() {
|
||||
public void invoke(RealmResource realm) {
|
||||
realm.flows().addExecution("nosuch", Collections.<String, String>emptyMap());
|
||||
realm.flows().addExecution("nosuch", Collections.<String, Object>emptyMap());
|
||||
}
|
||||
}, Resource.REALM, true);
|
||||
invoke(new Invocation() {
|
||||
|
|
|
@ -84,6 +84,25 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for an execution located before the provided execution on the same level of
|
||||
* an authentication flow.
|
||||
*
|
||||
* @param execution execution to find a neighbor for
|
||||
* @param executions list of executions to search in
|
||||
* @return execution, or null if not found
|
||||
*/
|
||||
public static AuthenticationExecutionInfoRepresentation findPreviousExecution(AuthenticationExecutionInfoRepresentation execution, List<AuthenticationExecutionInfoRepresentation> executions) {
|
||||
for (AuthenticationExecutionInfoRepresentation exec : executions) {
|
||||
if (exec.getLevel() != execution.getLevel()) {
|
||||
continue;
|
||||
}
|
||||
if (exec.getIndex() == execution.getIndex() - 1) {
|
||||
return exec;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static AuthenticationFlowRepresentation findFlowByAlias(String alias, List<AuthenticationFlowRepresentation> flows) {
|
||||
for (AuthenticationFlowRepresentation flow : flows) {
|
||||
|
@ -101,6 +120,7 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
|
|||
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 priority - " + actual.getProviderId(), expected.getPriority(), actual.getPriority());
|
||||
Assert.assertEquals("Execution authentication flow - " + actual.getProviderId(), expected.getAuthenticationFlow(), actual.getAuthenticationFlow());
|
||||
Assert.assertEquals("Execution requirement choices - " + actual.getProviderId(), expected.getRequirementChoices(), actual.getRequirementChoices());
|
||||
}
|
||||
|
@ -153,7 +173,8 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
|
|||
}
|
||||
|
||||
AuthenticationExecutionInfoRepresentation newExecInfo(String displayName, String providerId, Boolean configurable,
|
||||
int level, int index, String requirement, Boolean authFlow, String[] choices) {
|
||||
int level, int index, String requirement, Boolean authFlow, String[] choices,
|
||||
int priority) {
|
||||
|
||||
AuthenticationExecutionInfoRepresentation execution = new AuthenticationExecutionInfoRepresentation();
|
||||
execution.setRequirement(requirement);
|
||||
|
@ -163,6 +184,7 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
|
|||
execution.setLevel(level);
|
||||
execution.setIndex(index);
|
||||
execution.setAuthenticationFlow(authFlow);
|
||||
execution.setPriority(priority);
|
||||
if (choices != null) {
|
||||
execution.setRequirementChoices(Arrays.asList(choices));
|
||||
}
|
||||
|
@ -170,9 +192,9 @@ public abstract class AbstractAuthenticationTest extends AbstractKeycloakTest {
|
|||
}
|
||||
|
||||
void addExecInfo(List<AuthenticationExecutionInfoRepresentation> target, String displayName, String providerId, Boolean configurable,
|
||||
int level, int index, String requirement, Boolean authFlow, String[] choices) {
|
||||
int level, int index, String requirement, Boolean authFlow, String[] choices, int priority) {
|
||||
|
||||
AuthenticationExecutionInfoRepresentation exec = newExecInfo(displayName, providerId, configurable, level, index, requirement, authFlow, choices);
|
||||
AuthenticationExecutionInfoRepresentation exec = newExecInfo(displayName, providerId, configurable, level, index, requirement, authFlow, choices, priority);
|
||||
target.add(exec);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public class AuthenticatorConfigTest extends AbstractAuthenticationTest {
|
|||
AuthenticationFlowRepresentation flowRep = newFlow("firstBrokerLogin2", "firstBrokerLogin2", "basic-flow", true, false);
|
||||
createFlow(flowRep);
|
||||
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("provider", IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID);
|
||||
authMgmtResource.addExecution("firstBrokerLogin2", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionPath("firstBrokerLogin2"), params, ResourceType.AUTH_EXECUTION);
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
@Test
|
||||
public void testUpdateAuthenticatorConfig() {
|
||||
// copy built-in flow so we get a new editable flow
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", "new-browser-flow");
|
||||
Response response = authMgmtResource.copy("browser", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params, ResourceType.AUTH_FLOW);
|
||||
|
@ -104,7 +104,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
public void testAddRemoveExecution() {
|
||||
|
||||
// try add execution to built-in flow
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("provider", "idp-review-profile");
|
||||
try {
|
||||
authMgmtResource.addExecution("browser", params);
|
||||
|
@ -153,7 +153,9 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
// we'll need auth-cookie later
|
||||
AuthenticationExecutionInfoRepresentation authCookieExec = findExecutionByProvider("auth-cookie", executionReps);
|
||||
|
||||
compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 4, DISABLED, null, new String[]{REQUIRED, ALTERNATIVE,DISABLED}), exec);
|
||||
AuthenticationExecutionInfoRepresentation previousExecution = findPreviousExecution(exec, executionReps);
|
||||
Assert.assertNotNull(previousExecution);
|
||||
compareExecution(newExecInfo("Review Profile", "idp-review-profile", true, 0, 4, DISABLED, null, new String[]{REQUIRED, ALTERNATIVE,DISABLED}, previousExecution.getPriority() + 1), exec);
|
||||
|
||||
// remove execution
|
||||
authMgmtResource.removeExecution(exec.getId());
|
||||
|
@ -223,7 +225,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
|
||||
// Note: there is no checking in addExecution if requirement is one of requirementChoices
|
||||
// Thus we can have OPTIONAL which is neither ALTERNATIVE, nor DISABLED
|
||||
compareExecution(newExecInfo("Cookie", "auth-cookie", false, 0, 3, CONDITIONAL, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}), exec);
|
||||
compareExecution(newExecInfo("Cookie", "auth-cookie", false, 0, 0, CONDITIONAL, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10), exec);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -234,9 +236,11 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider("auth-cookie", executionReps);
|
||||
|
||||
Assert.assertEquals("auth-cookie set to ALTERNATIVE", ALTERNATIVE, exec.getRequirement());
|
||||
Assert.assertEquals("auth-cookie is first in the flow", exec.getIndex(), 0);
|
||||
|
||||
// switch from DISABLED to ALTERNATIVE
|
||||
exec.setRequirement(DISABLED);
|
||||
exec.setPriority(Integer.MAX_VALUE);
|
||||
authMgmtResource.updateExecutions("browser", exec);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.UPDATE, AdminEventPaths.authUpdateExecutionPath("browser"), exec, ResourceType.AUTH_EXECUTION);
|
||||
|
||||
|
@ -245,6 +249,13 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
|
||||
// get current auth-cookie execution
|
||||
AuthenticationExecutionInfoRepresentation exec2 = findExecutionByProvider("auth-cookie", executionReps);
|
||||
|
||||
// The execution is expected to be last after priority change
|
||||
long expectedIndex = executionReps.stream()
|
||||
.filter(r -> r.getLevel() == exec2.getLevel())
|
||||
.count() - 1;
|
||||
exec.setIndex(Math.toIntExact(expectedIndex));
|
||||
|
||||
compareExecution(exec, exec2);
|
||||
}
|
||||
|
||||
|
@ -255,7 +266,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
createFlow(clientFlow);
|
||||
|
||||
// Add execution to it
|
||||
Map<String, String> executionData = new HashMap<>();
|
||||
Map<String, Object> executionData = new HashMap<>();
|
||||
executionData.put("provider", ClientIdAndSecretAuthenticator.PROVIDER_ID);
|
||||
authMgmtResource.addExecution("new-client-flow", executionData);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionPath("new-client-flow"), executionData, ResourceType.AUTH_EXECUTION);
|
||||
|
@ -319,7 +330,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
|
||||
@Test
|
||||
public void testRequirementsInExecution() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
String newBrowserFlow = "new-exec-flow";
|
||||
|
||||
params.put("newName", newBrowserFlow);
|
||||
|
@ -337,7 +348,7 @@ public class ExecutionTest extends AbstractAuthenticationTest {
|
|||
assertAdminEvents.assertEvent(testRealmId, OperationType.DELETE, AdminEventPaths.authFlowPath(rep.getId()), ResourceType.AUTH_FLOW);
|
||||
}
|
||||
|
||||
private void addExecutionCheckReq(String flow, String providerID, HashMap<String, String> params, String expectedRequirement) {
|
||||
private void addExecutionCheckReq(String flow, String providerID, HashMap<String, Object> params, String expectedRequirement) {
|
||||
params.put("provider", providerID);
|
||||
authMgmtResource.addExecution(flow, params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionPath(flow), params, ResourceType.AUTH_EXECUTION);
|
||||
|
|
|
@ -108,7 +108,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
}
|
||||
|
||||
private void addFlowToParent(String parentAlias, String childAlias) {
|
||||
Map<String, String> data = new HashMap<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("alias", childAlias);
|
||||
data.put("type", "generic");
|
||||
data.put("description", childAlias + " flow");
|
||||
|
@ -179,14 +179,14 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
|
||||
|
||||
// add execution flow to some parent flow
|
||||
Map<String, String> data = new HashMap<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("alias", "SomeFlow");
|
||||
data.put("type", "basic-flow");
|
||||
data.put("description", "Test flow");
|
||||
// This tests against a regression in KEYCLOAK-16656
|
||||
data.put("provider", "registration-page-form");
|
||||
|
||||
Map<String, String> data2 = new HashMap<>();
|
||||
Map<String, Object> data2 = new HashMap<>();
|
||||
data2.put("alias", "SomeFlow2");
|
||||
data2.put("type", "form-flow");
|
||||
data2.put("description", "Test flow 2");
|
||||
|
@ -265,7 +265,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
@Test
|
||||
public void testCopyFlow() {
|
||||
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", "clients");
|
||||
|
||||
// copy using existing alias as new name
|
||||
|
@ -321,7 +321,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
@Test
|
||||
// KEYCLOAK-2580
|
||||
public void addExecutionFlow() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", "parent");
|
||||
Response response = authMgmtResource.copy("browser", params);
|
||||
Assert.assertEquals(201, response.getStatus());
|
||||
|
@ -347,7 +347,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
List<AuthenticationFlowRepresentation> flows;
|
||||
|
||||
//copy an existing one first
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", "Copy of browser");
|
||||
Response response = authMgmtResource.copy("browser", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params, ResourceType.AUTH_FLOW);
|
||||
|
@ -423,7 +423,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
|
||||
@Test
|
||||
public void editExecutionFlowTest() {
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
List<AuthenticationExecutionInfoRepresentation> executionReps;
|
||||
//create new parent flow
|
||||
AuthenticationFlowRepresentation newFlow = newFlow("Parent-Flow", "This is a parent flow", "basic-flow", true, false);
|
||||
|
@ -483,6 +483,66 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
Assert.assertEquals("This is another child flow3", executionReps.get(0).getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritySetTest() {
|
||||
//create new parent flow
|
||||
AuthenticationFlowRepresentation newFlow = newFlow("Parent-Flow", "This is a parent flow", "basic-flow", true, false);
|
||||
createFlow(newFlow);
|
||||
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("alias", "Child-Flow1");
|
||||
params.put("description", "This is a child flow");
|
||||
params.put("provider", "registration-page-form");
|
||||
params.put("type", "basic-flow");
|
||||
params.put("priority", 50);
|
||||
|
||||
authMgmtResource.addExecutionFlow("Parent-Flow", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("Parent-Flow"), params, ResourceType.AUTH_EXECUTION_FLOW);
|
||||
|
||||
params.clear();
|
||||
params.put("alias", "Child-Flow2");
|
||||
params.put("description", "This is a second child flow");
|
||||
params.put("provider", "registration-page-form");
|
||||
params.put("type", "basic-flow");
|
||||
params.put("priority", 10);
|
||||
|
||||
authMgmtResource.addExecutionFlow("Parent-Flow", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("Parent-Flow"), params, ResourceType.AUTH_EXECUTION_FLOW);
|
||||
|
||||
params.clear();
|
||||
params.put("alias", "Child-Flow3");
|
||||
params.put("description", "This is a third child flow");
|
||||
params.put("provider", "registration-page-form");
|
||||
params.put("type", "basic-flow");
|
||||
params.put("priority", 20);
|
||||
|
||||
authMgmtResource.addExecutionFlow("Parent-Flow", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("Parent-Flow"), params, ResourceType.AUTH_EXECUTION_FLOW);
|
||||
|
||||
List<AuthenticationExecutionInfoRepresentation> executionReps = authMgmtResource.getExecutions("Parent-Flow");
|
||||
// Verify the initial order and priority value
|
||||
Assert.assertEquals("Child-Flow2", executionReps.get(0).getDisplayName());
|
||||
Assert.assertEquals(10, executionReps.get(0).getPriority());
|
||||
Assert.assertEquals("Child-Flow3", executionReps.get(1).getDisplayName());
|
||||
Assert.assertEquals(20, executionReps.get(1).getPriority());
|
||||
Assert.assertEquals("Child-Flow1", executionReps.get(2).getDisplayName());
|
||||
Assert.assertEquals(50, executionReps.get(2).getPriority());
|
||||
|
||||
// Move last execution to the beginning
|
||||
AuthenticationExecutionInfoRepresentation lastToFirst = executionReps.get(2);
|
||||
lastToFirst.setPriority(5);
|
||||
authMgmtResource.updateExecutions("Parent-Flow", lastToFirst);
|
||||
executionReps = authMgmtResource.getExecutions("Parent-Flow");
|
||||
|
||||
// Verify new order and priority
|
||||
Assert.assertEquals("Child-Flow1", executionReps.get(0).getDisplayName());
|
||||
Assert.assertEquals(5, executionReps.get(0).getPriority());
|
||||
Assert.assertEquals("Child-Flow2", executionReps.get(1).getDisplayName());
|
||||
Assert.assertEquals(10, executionReps.get(1).getPriority());
|
||||
Assert.assertEquals("Child-Flow3", executionReps.get(2).getDisplayName());
|
||||
Assert.assertEquals(20, executionReps.get(2).getPriority());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failWithLongDescription() throws IOException {
|
||||
ContainerAssume.assumeAuthServerQuarkus();
|
||||
|
@ -525,7 +585,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
Assert.assertNotNull("There is no builtin flow", flow);
|
||||
|
||||
// adding an execution should fail
|
||||
Map<String, String> data = new HashMap<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("provider", "allow-access-authenticator");
|
||||
BadRequestException e = Assert.assertThrows(BadRequestException.class, () -> authMgmtResource.addExecution(flow.getAlias(), data));
|
||||
OAuth2ErrorRepresentation error = e.getResponse().readEntity(OAuth2ErrorRepresentation.class);
|
||||
|
@ -579,7 +639,7 @@ public class FlowTest extends AbstractAuthenticationTest {
|
|||
}
|
||||
|
||||
String newFlowName = "Duplicated of " + DefaultAuthenticationFlows.BROWSER_FLOW;
|
||||
Map<String, String> copyFlowParams = Map.of("newName", newFlowName);
|
||||
Map<String, Object> copyFlowParams = Map.of("newName", newFlowName);
|
||||
authMgmtResource.copy(existingFlow.getAlias(), copyFlowParams).close();
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), copyFlowParams, ResourceType.AUTH_FLOW);
|
||||
|
||||
|
|
|
@ -129,14 +129,14 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
|
|||
addExecExport(flow, "forms", false, null, true, null, ALTERNATIVE, 30);
|
||||
|
||||
List<AuthenticationExecutionInfoRepresentation> execs = new LinkedList<>();
|
||||
addExecInfo(execs, "Cookie", "auth-cookie", false, 0, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Kerberos", "auth-spnego", false, 0, 1, DISABLED, null, kerberosAuthExpectedChoices);
|
||||
addExecInfo(execs, "Identity Provider Redirector", "identity-provider-redirector", true, 0, 2, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "forms", null, false, 0, 3, ALTERNATIVE, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Username Password Form", "auth-username-password-form", false, 1, 0, REQUIRED, null, new String[]{REQUIRED});
|
||||
addExecInfo(execs, "Browser - Conditional OTP", null, false, 1, 1, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 2, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "OTP Form", "auth-otp-form", false, 2, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Cookie", "auth-cookie", false, 0, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10);
|
||||
addExecInfo(execs, "Kerberos", "auth-spnego", false, 0, 1, DISABLED, null, kerberosAuthExpectedChoices, 20);
|
||||
addExecInfo(execs, "Identity Provider Redirector", "identity-provider-redirector", true, 0, 2, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 25);
|
||||
addExecInfo(execs, "forms", null, false, 0, 3, ALTERNATIVE, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 30);
|
||||
addExecInfo(execs, "Username Password Form", "auth-username-password-form", false, 1, 0, REQUIRED, null, new String[]{REQUIRED}, 10);
|
||||
addExecInfo(execs, "Browser - Conditional OTP", null, false, 1, 1, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 20);
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 2, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED}, 10);
|
||||
addExecInfo(execs, "OTP Form", "auth-otp-form", false, 2, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 20);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
flow = newFlow("clients", "Base authentication for clients", "client-flow", true, true);
|
||||
|
@ -146,10 +146,10 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
|
|||
addExecExport(flow, null, false, "client-x509", false, null, ALTERNATIVE, 40);
|
||||
|
||||
execs = new LinkedList<>();
|
||||
addExecInfo(execs, "Client Id and Secret", "client-secret", false, 0, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Signed Jwt", "client-jwt", false, 0, 1, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Signed Jwt with Client Secret", "client-secret-jwt", false, 0, 2, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "X509 Certificate", "client-x509", false, 0, 3, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Client Id and Secret", "client-secret", false, 0, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10);
|
||||
addExecInfo(execs, "Signed Jwt", "client-jwt", false, 0, 1, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 20);
|
||||
addExecInfo(execs, "Signed Jwt with Client Secret", "client-secret-jwt", false, 0, 2, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 30);
|
||||
addExecInfo(execs, "X509 Certificate", "client-x509", false, 0, 3, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 40);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
flow = newFlow("direct grant", "OpenID Connect Resource Owner Grant", "basic-flow", true, true);
|
||||
|
@ -158,18 +158,18 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
|
|||
addExecExport(flow, "Direct Grant - Conditional OTP", false, null, true, null, CONDITIONAL, 30);
|
||||
|
||||
execs = new LinkedList<>();
|
||||
addExecInfo(execs, "Username Validation", "direct-grant-validate-username", false, 0, 0, REQUIRED, null, new String[]{REQUIRED});
|
||||
addExecInfo(execs, "Password", "direct-grant-validate-password", false, 0, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE,DISABLED});
|
||||
addExecInfo(execs, "Direct Grant - Conditional OTP", null, false, 0, 2, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 1, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "OTP", "direct-grant-validate-otp", false, 1, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Username Validation", "direct-grant-validate-username", false, 0, 0, REQUIRED, null, new String[]{REQUIRED}, 10);
|
||||
addExecInfo(execs, "Password", "direct-grant-validate-password", false, 0, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE,DISABLED}, 20);
|
||||
addExecInfo(execs, "Direct Grant - Conditional OTP", null, false, 0, 2, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 30);
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 1, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED}, 10);
|
||||
addExecInfo(execs, "OTP", "direct-grant-validate-otp", false, 1, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 20);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
flow = newFlow("docker auth", "Used by Docker clients to authenticate against the IDP", "basic-flow", true, true);
|
||||
addExecExport(flow, null, false, "docker-http-basic-authenticator", false, null, REQUIRED, 10);
|
||||
|
||||
execs = new LinkedList<>();
|
||||
addExecInfo(execs, "Docker Authenticator", "docker-http-basic-authenticator", false, 0, 0, REQUIRED, null, new String[]{REQUIRED});
|
||||
addExecInfo(execs, "Docker Authenticator", "docker-http-basic-authenticator", false, 0, 0, REQUIRED, null, new String[]{REQUIRED}, 10);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
flow = newFlow("first broker login", "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
|
||||
|
@ -178,29 +178,29 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
|
|||
addExecExport(flow, "User creation or linking", false, null, true, null, REQUIRED, 20);
|
||||
|
||||
execs = new LinkedList<>();
|
||||
addExecInfo(execs, "Review Profile", "idp-review-profile", true, 0, 0, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "User creation or linking", null, false, 0, 1, REQUIRED, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Create User If Unique", "idp-create-user-if-unique", true, 1, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Handle Existing Account", null, false, 1, 1, ALTERNATIVE, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Confirm link existing account", "idp-confirm-link", false, 2, 0, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Account verification options", null, false, 2, 1, REQUIRED, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Verify existing account by Email", "idp-email-verification", false, 3, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Verify Existing Account by Re-authentication", null, false, 3, 1, ALTERNATIVE, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Username Password Form for identity provider reauthentication", "idp-username-password-form", false, 4, 0, REQUIRED, null, new String[]{REQUIRED});
|
||||
addExecInfo(execs, "First broker login - Conditional OTP", null, false, 4, 1, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 5, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "OTP Form", "auth-otp-form", false, 5, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Review Profile", "idp-review-profile", true, 0, 0, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10);
|
||||
addExecInfo(execs, "User creation or linking", null, false, 0, 1, REQUIRED, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 20);
|
||||
addExecInfo(execs, "Create User If Unique", "idp-create-user-if-unique", true, 1, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10);
|
||||
addExecInfo(execs, "Handle Existing Account", null, false, 1, 1, ALTERNATIVE, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 20);
|
||||
addExecInfo(execs, "Confirm link existing account", "idp-confirm-link", false, 2, 0, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10);
|
||||
addExecInfo(execs, "Account verification options", null, false, 2, 1, REQUIRED, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 20);
|
||||
addExecInfo(execs, "Verify existing account by Email", "idp-email-verification", false, 3, 0, ALTERNATIVE, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 10);
|
||||
addExecInfo(execs, "Verify Existing Account by Re-authentication", null, false, 3, 1, ALTERNATIVE, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 20);
|
||||
addExecInfo(execs, "Username Password Form for identity provider reauthentication", "idp-username-password-form", false, 4, 0, REQUIRED, null, new String[]{REQUIRED}, 10);
|
||||
addExecInfo(execs, "First broker login - Conditional OTP", null, false, 4, 1, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 20);
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 5, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED}, 10);
|
||||
addExecInfo(execs, "OTP Form", "auth-otp-form", false, 5, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 20);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
flow = newFlow("registration", "registration flow", "basic-flow", true, true);
|
||||
addExecExport(flow, "registration form", false, "registration-page-form", true, null, REQUIRED, 10);
|
||||
|
||||
execs = new LinkedList<>();
|
||||
addExecInfo(execs, "registration form", "registration-page-form", false, 0, 0, REQUIRED, true, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "Registration User Profile Creation", "registration-user-creation", false, 1, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "Password Validation", "registration-password-action", false, 1, 1, REQUIRED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "reCAPTCHA", "registration-recaptcha-action", true, 1, 2, DISABLED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "Terms and conditions", "registration-terms-and-conditions", false, 1, 3, DISABLED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "registration form", "registration-page-form", false, 0, 0, REQUIRED, true, new String[]{REQUIRED, DISABLED}, 10);
|
||||
addExecInfo(execs, "Registration User Profile Creation", "registration-user-creation", false, 1, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED}, 20);
|
||||
addExecInfo(execs, "Password Validation", "registration-password-action", false, 1, 1, REQUIRED, null, new String[]{REQUIRED, DISABLED}, 50);
|
||||
addExecInfo(execs, "reCAPTCHA", "registration-recaptcha-action", true, 1, 2, DISABLED, null, new String[]{REQUIRED, DISABLED}, 60);
|
||||
addExecInfo(execs, "Terms and conditions", "registration-terms-and-conditions", false, 1, 3, DISABLED, null, new String[]{REQUIRED, DISABLED}, 70);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
flow = newFlow("reset credentials", "Reset credentials for a user if they forgot their password or something", "basic-flow", true, true);
|
||||
|
@ -210,12 +210,12 @@ public class InitialFlowsTest extends AbstractAuthenticationTest {
|
|||
addExecExport(flow, "Reset - Conditional OTP", false, null, true, null, CONDITIONAL, 40);
|
||||
|
||||
execs = new LinkedList<>();
|
||||
addExecInfo(execs, "Choose User", "reset-credentials-choose-user", false, 0, 0, REQUIRED, null, new String[]{REQUIRED});
|
||||
addExecInfo(execs, "Send Reset Email", "reset-credential-email", false, 0, 1, REQUIRED, null, new String[]{REQUIRED});
|
||||
addExecInfo(execs, "Reset Password", "reset-password", false, 0, 2, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Reset - Conditional OTP", null, false, 0, 3, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL});
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 1, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED});
|
||||
addExecInfo(execs, "Reset OTP", "reset-otp", true, 1, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED});
|
||||
addExecInfo(execs, "Choose User", "reset-credentials-choose-user", false, 0, 0, REQUIRED, null, new String[]{REQUIRED}, 10);
|
||||
addExecInfo(execs, "Send Reset Email", "reset-credential-email", false, 0, 1, REQUIRED, null, new String[]{REQUIRED}, 20);
|
||||
addExecInfo(execs, "Reset Password", "reset-password", false, 0, 2, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 30);
|
||||
addExecInfo(execs, "Reset - Conditional OTP", null, false, 0, 3, CONDITIONAL, true, new String[]{REQUIRED, ALTERNATIVE, DISABLED, CONDITIONAL}, 40);
|
||||
addExecInfo(execs, "Condition - user configured", "conditional-user-configured", false, 1, 0, REQUIRED, null, new String[]{REQUIRED, DISABLED}, 10);
|
||||
addExecInfo(execs, "Reset OTP", "reset-otp", true, 1, 1, REQUIRED, null, new String[]{REQUIRED, ALTERNATIVE, DISABLED}, 20);
|
||||
expected.add(new FlowExecutions(flow, execs));
|
||||
|
||||
return expected;
|
||||
|
|
|
@ -40,7 +40,7 @@ public class RegistrationFlowTest extends AbstractAuthenticationTest {
|
|||
createFlow(flowRep);
|
||||
|
||||
// add registration execution form flow
|
||||
Map<String, String> data = new HashMap<>();
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("alias", "registrationForm2");
|
||||
data.put("type", "form-flow");
|
||||
data.put("description", "registrationForm2 flow");
|
||||
|
@ -49,7 +49,7 @@ public class RegistrationFlowTest extends AbstractAuthenticationTest {
|
|||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authAddExecutionFlowPath("registration2"), data, ResourceType.AUTH_EXECUTION_FLOW);
|
||||
|
||||
// Should fail to add execution under top level flow
|
||||
Map<String, String> data2 = new HashMap<>();
|
||||
Map<String, Object> data2 = new HashMap<>();
|
||||
data2.put("provider", "registration-password-action");
|
||||
try {
|
||||
authMgmtResource.addExecution("registration2", data2);
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ShiftExecutionTest extends AbstractAuthenticationTest {
|
|||
public void testShiftExecution() {
|
||||
|
||||
// copy built-in flow so we get a new editable flow
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", "Copy of browser");
|
||||
Response response = authMgmtResource.copy("browser", params);
|
||||
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params, ResourceType.AUTH_FLOW);
|
||||
|
|
|
@ -212,7 +212,7 @@ public class CustomFlowTest extends AbstractFlowTest {
|
|||
@Test
|
||||
public void testRequiredAfterAlternative() {
|
||||
AuthenticationManagementResource authMgmtResource = testRealm().flows();
|
||||
Map<String, String> params = new HashMap();
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
String flowAlias = "Browser Flow With Extra";
|
||||
params.put("newName", flowAlias);
|
||||
Response response = authMgmtResource.copy("browser", params);
|
||||
|
|
|
@ -196,7 +196,7 @@ public class DeployedScriptAuthenticatorTest extends AbstractFlowTest {
|
|||
AuthenticationManagementResource authMgmtResource = adminClient.realm(TEST_REALM_NAME).flows();
|
||||
|
||||
// Endpoint used by admin console
|
||||
Map<String, String> scriptExecution = new HashMap<>();
|
||||
Map<String, Object> scriptExecution = new HashMap<>();
|
||||
scriptExecution.put("provider", "script-authenticator-a.js");
|
||||
|
||||
// It should be possible to add another script-authenticator to the flow
|
||||
|
@ -224,7 +224,7 @@ public class DeployedScriptAuthenticatorTest extends AbstractFlowTest {
|
|||
}
|
||||
|
||||
// Test copy flow is OK
|
||||
Map<String, String> newFlow = new HashMap<>();
|
||||
Map<String, Object> newFlow = new HashMap<>();
|
||||
newFlow.put("newName", "Copy of script flow");
|
||||
Response resp = authMgmtResource.copy("scriptBrowser", newFlow);
|
||||
Assert.assertEquals(201, resp.getStatus());
|
||||
|
|
|
@ -370,7 +370,7 @@ public abstract class AbstractX509AuthenticationTest extends AbstractTestRealmKe
|
|||
|
||||
AuthenticationFlowRepresentation copyFlow(String existingFlow, String newFlow) {
|
||||
// copy that should succeed
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
HashMap<String, Object> params = new HashMap<>();
|
||||
params.put("newName", newFlow);
|
||||
Response response = authMgmtResource.copy(existingFlow, params);
|
||||
assertAdminEvents.assertEvent(realmId, OperationType.CREATE, Encode.decode(AdminEventPaths.authCopyFlowPath(existingFlow)), params, ResourceType.AUTH_FLOW);
|
||||
|
|
Loading…
Reference in a new issue