diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java index 269301c924..a82537ec95 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java @@ -18,7 +18,7 @@ package org.keycloak.services.resources.admin; import org.jboss.logging.Logger; import org.jboss.resteasy.annotations.cache.NoCache; -import org.jboss.resteasy.spi.BadRequestException; +import javax.ws.rs.BadRequestException; import javax.ws.rs.NotFoundException; import org.keycloak.authentication.AuthenticationFlow; import org.keycloak.authentication.Authenticator; @@ -459,7 +459,13 @@ public class AuthenticationManagementResource { AuthenticationExecutionModel execution = new AuthenticationExecutionModel(); execution.setParentFlow(parentFlow.getId()); - execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED); + + ConfigurableAuthenticatorFactory conf = (ConfigurableAuthenticatorFactory) f; + if (conf.getRequirementChoices().length == 1) + execution.setRequirement(conf.getRequirementChoices()[0]); + else + execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED); + execution.setAuthenticatorFlow(false); execution.setAuthenticator(provider); execution.setPriority(getNextPriority(parentFlow)); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java index 4b5ef46801..01adb3d1c2 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/authentication/ExecutionTest.java @@ -20,6 +20,9 @@ package org.keycloak.testsuite.admin.authentication; import org.junit.Assert; import org.junit.Test; import org.keycloak.authentication.AuthenticationFlow; +import org.keycloak.authentication.authenticators.browser.UsernameFormFactory; +import org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticatorFactory; +import org.keycloak.authentication.authenticators.challenge.NoCookieFlowRedirectAuthenticatorFactory; import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; @@ -37,6 +40,7 @@ import javax.ws.rs.core.Response; import java.util.HashMap; import java.util.List; import java.util.Map; + import static org.hamcrest.Matchers.hasItems; /** @@ -312,4 +316,40 @@ public class ExecutionTest extends AbstractAuthenticationTest { authMgmtResource.deleteFlow(rep.getId()); assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authFlowPath(rep.getId()), ResourceType.AUTH_FLOW); } + + @Test + public void testRequirementsInExecution() { + HashMap params = new HashMap<>(); + String newBrowserFlow = "new-exec-flow"; + + params.put("newName", newBrowserFlow); + try (Response response = authMgmtResource.copy("browser", params)) { + assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authCopyFlowPath("browser"), params, ResourceType.AUTH_FLOW); + Assert.assertEquals("Copy flow", 201, response.getStatus()); + } + + addExecutionCheckReq(newBrowserFlow, UsernameFormFactory.PROVIDER_ID, params, REQUIRED); + addExecutionCheckReq(newBrowserFlow, WebAuthnAuthenticatorFactory.PROVIDER_ID, params, DISABLED); + addExecutionCheckReq(newBrowserFlow, NoCookieFlowRedirectAuthenticatorFactory.PROVIDER_ID, params, REQUIRED); + + AuthenticationFlowRepresentation rep = findFlowByAlias(newBrowserFlow, authMgmtResource.getFlows()); + Assert.assertNotNull(rep); + authMgmtResource.deleteFlow(rep.getId()); + assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authFlowPath(rep.getId()), ResourceType.AUTH_FLOW); + } + + private void addExecutionCheckReq(String flow, String providerID, HashMap params, String expectedRequirement) { + params.put("provider", providerID); + authMgmtResource.addExecution(flow, params); + assertAdminEvents.assertEvent(REALM_NAME, OperationType.CREATE, AdminEventPaths.authAddExecutionPath(flow), params, ResourceType.AUTH_EXECUTION); + + List executionReps = authMgmtResource.getExecutions(flow); + AuthenticationExecutionInfoRepresentation exec = findExecutionByProvider(providerID, executionReps); + + Assert.assertNotNull(exec); + Assert.assertEquals(expectedRequirement, exec.getRequirement()); + + authMgmtResource.removeExecution(exec.getId()); + assertAdminEvents.assertEvent(REALM_NAME, OperationType.DELETE, AdminEventPaths.authExecutionPath(exec.getId()), ResourceType.AUTH_EXECUTION); + } }