diff --git a/pom.xml b/pom.xml
index e129d6246..050d835de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,7 +59,7 @@
UTF-8
UTF-8
- 21.0.1
+ 18.0.2
3.2.0
10.0
diff --git a/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java b/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java
index 26ba23a3a..6184f99f7 100644
--- a/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java
+++ b/src/main/java/de/adorsys/keycloak/config/service/ExecutionFlowsImportService.java
@@ -21,7 +21,6 @@
package de.adorsys.keycloak.config.service;
import de.adorsys.keycloak.config.exception.ImportProcessingException;
-import de.adorsys.keycloak.config.exception.InvalidImportException;
import de.adorsys.keycloak.config.model.RealmImport;
import de.adorsys.keycloak.config.repository.AuthenticatorConfigRepository;
import de.adorsys.keycloak.config.repository.ExecutionFlowRepository;
@@ -148,13 +147,6 @@ private void createSubFlowByExecutionFlow(
executionToImport.getFlowAlias(), realmImport.getRealm()
);
- if (!Objects.equals(executionToImport.getAuthenticator(), null) && !Objects.equals(subFlow.getProviderId(), "form-flow")) {
- throw new InvalidImportException(String.format(
- "Execution property authenticator '%s' can be only set if the sub-flow '%s' type is 'form-flow'.",
- executionToImport.getAuthenticator(), subFlow.getAlias()
- ));
- }
-
HashMap executionFlow = new HashMap<>();
executionFlow.put("alias", executionToImport.getFlowAlias());
executionFlow.put("provider", executionToImport.getAuthenticator());
diff --git a/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java b/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java
index 5a92dbe8d..be0412dee 100644
--- a/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java
+++ b/src/test/java/de/adorsys/keycloak/config/normalize/AbstractNormalizeTest.java
@@ -25,6 +25,7 @@
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
+import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -33,6 +34,7 @@
@ExtendWith(SpringExtension.class)
@ExtendWith(GithubActionsExtension.class)
+@ExtendWith(OutputCaptureExtension.class)
@ContextConfiguration(
classes = {NormalizeTestConfiguration.class},
initializers = {ConfigDataApplicationContextInitializer.class}
diff --git a/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceConfigIT.java b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceConfigIT.java
new file mode 100644
index 000000000..d9a2ef250
--- /dev/null
+++ b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceConfigIT.java
@@ -0,0 +1,81 @@
+package de.adorsys.keycloak.config.service.normalize;
+
+import de.adorsys.keycloak.config.normalize.AbstractNormalizeTest;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
+import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
+import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.system.CapturedOutput;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+class AuthFlowNormalizationServiceConfigIT extends AbstractNormalizeTest {
+
+ @Autowired
+ AuthFlowNormalizationService service;
+
+ @Test
+ public void testNormalizeAuthConfigsWithEmptyListsIsNull() {
+ var resultingAuthConfig = service.normalizeAuthConfig(new ArrayList<>(), new ArrayList<>());
+ Assertions.assertThat(resultingAuthConfig).isNull();
+ }
+
+ @Test
+ public void testNormalizeAuthConfigsAreRemovedWithoutAliasReference(CapturedOutput output) {
+ AuthenticatorConfigRepresentation authenticatorConfigRepresentation = new AuthenticatorConfigRepresentation();
+ authenticatorConfigRepresentation.setAlias("config2");
+
+ AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation();
+
+ AuthenticationExecutionExportRepresentation authenticationExecutionExportRepresentation = new AuthenticationExecutionExportRepresentation();
+ authenticationExecutionExportRepresentation.setAuthenticatorConfig("config1");
+ authenticationFlowRepresentation.setAuthenticationExecutions(List.of(authenticationExecutionExportRepresentation));
+
+ var resultingAuthConfig = service.normalizeAuthConfig(List.of(authenticatorConfigRepresentation), List.of(authenticationFlowRepresentation));
+
+ Assertions.assertThat(resultingAuthConfig).isNull();
+ Assertions.assertThat(output.getOut()).contains("Some authenticator configs are unused.");
+ }
+
+ @Test
+ public void testNormalizeAuthConfigsRemainWithAliasReference() {
+ AuthenticatorConfigRepresentation authenticatorConfigRepresentation = new AuthenticatorConfigRepresentation();
+ authenticatorConfigRepresentation.setAlias("config1");
+
+ AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation();
+
+ AuthenticationExecutionExportRepresentation authenticationExecutionExportRepresentation = new AuthenticationExecutionExportRepresentation();
+ authenticationExecutionExportRepresentation.setAuthenticatorConfig("config1");
+ authenticationFlowRepresentation.setAuthenticationExecutions(List.of(authenticationExecutionExportRepresentation));
+
+ var resultingAuthConfig = service.normalizeAuthConfig(List.of(authenticatorConfigRepresentation), List.of(authenticationFlowRepresentation));
+
+ Assertions.assertThat(resultingAuthConfig).containsExactlyInAnyOrder(authenticatorConfigRepresentation);
+ }
+
+ @Test
+ public void testNormalizeAuthConfigsCheckedForDuplicates(CapturedOutput output) {
+ AuthenticatorConfigRepresentation authenticatorConfigRepresentation1 = new AuthenticatorConfigRepresentation();
+ authenticatorConfigRepresentation1.setId(UUID.randomUUID().toString());
+ authenticatorConfigRepresentation1.setAlias("config1");
+
+ AuthenticatorConfigRepresentation authenticatorConfigRepresentation2 = new AuthenticatorConfigRepresentation();
+ authenticatorConfigRepresentation2.setId(UUID.randomUUID().toString());
+ authenticatorConfigRepresentation2.setAlias("config1");
+
+ AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation();
+
+ AuthenticationExecutionExportRepresentation authenticationExecutionExportRepresentation = new AuthenticationExecutionExportRepresentation();
+ authenticationExecutionExportRepresentation.setAuthenticatorConfig("config1");
+ authenticationFlowRepresentation.setAuthenticationExecutions(List.of(authenticationExecutionExportRepresentation));
+
+ var resultingAuthConfig = service.normalizeAuthConfig(List.of(authenticatorConfigRepresentation1, authenticatorConfigRepresentation2), List.of(authenticationFlowRepresentation));
+
+ Assertions.assertThat(resultingAuthConfig).containsExactlyInAnyOrder(authenticatorConfigRepresentation1, authenticatorConfigRepresentation2);
+ Assertions.assertThat(output.getOut()).contains("The following authenticator configs are duplicates: [config1]");
+ }
+}
diff --git a/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceFlowIT.java b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceFlowIT.java
new file mode 100644
index 000000000..a06f6a621
--- /dev/null
+++ b/src/test/java/de/adorsys/keycloak/config/service/normalize/AuthFlowNormalizationServiceFlowIT.java
@@ -0,0 +1,53 @@
+package de.adorsys.keycloak.config.service.normalize;
+
+import de.adorsys.keycloak.config.normalize.AbstractNormalizeTest;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.system.CapturedOutput;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class AuthFlowNormalizationServiceFlowIT extends AbstractNormalizeTest {
+
+ @Autowired
+ AuthFlowNormalizationService service;
+
+
+ @Test
+ public void testNormalizeAuthFlows() {
+ var resultingAuthFlows = service.normalizeAuthFlows(new ArrayList<>(), new ArrayList<>());
+ Assertions.assertThat(resultingAuthFlows).isNull();
+ }
+
+ @Test
+ public void testNormalizeAuthFlowsIgnoreBuiltInTrue() {
+ AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation();
+ authenticationFlowRepresentation.setBuiltIn(true);
+
+ AuthenticationFlowRepresentation authenticationFlowRepresentationBaseline = new AuthenticationFlowRepresentation();
+ authenticationFlowRepresentationBaseline.setBuiltIn(true);
+
+ var resultingAuthFlows = service.normalizeAuthFlows(List.of(authenticationFlowRepresentation), List.of(authenticationFlowRepresentationBaseline));
+
+ Assertions.assertThat(resultingAuthFlows).isNull();
+ }
+
+ @Test
+ public void testNormalizeAuthFlowsIgnoreBuiltInTrueButBaselineHasEntryCreatesRecreationWarning(CapturedOutput output) {
+ AuthenticationFlowRepresentation authenticationFlowRepresentation = new AuthenticationFlowRepresentation();
+ authenticationFlowRepresentation.setBuiltIn(true);
+
+ AuthenticationFlowRepresentation authenticationFlowRepresentationBaseline = new AuthenticationFlowRepresentation();
+ authenticationFlowRepresentationBaseline.setBuiltIn(false);
+ authenticationFlowRepresentationBaseline.setAlias("flow1");
+
+ var resultingAuthFlows = service.normalizeAuthFlows(List.of(authenticationFlowRepresentation), List.of(authenticationFlowRepresentationBaseline));
+
+ Assertions.assertThat(resultingAuthFlows).isNull();
+ Assertions.assertThat(output.getOut()).contains("Default realm authentication flow 'flow1' was deleted in exported realm. It may be reintroduced during import");
+
+ }
+}