Return next action if the current action is not supported in AIA
Closes #33513 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
8719e2d0d7
commit
44b1290917
2 changed files with 45 additions and 7 deletions
|
@ -1052,7 +1052,7 @@ public class AuthenticationManager {
|
|||
|
||||
final var kcAction = authSession.getClientNote(Constants.KC_ACTION);
|
||||
final var nextApplicableAction =
|
||||
getFirstApplicableRequiredAction(realm, authSession, user, kcAction);
|
||||
getFirstApplicableRequiredAction(realm, authSession, user, kcAction, new HashSet<>());
|
||||
if (nextApplicableAction != null) {
|
||||
return nextApplicableAction.getAlias();
|
||||
}
|
||||
|
@ -1232,7 +1232,7 @@ public class AuthenticationManager {
|
|||
HttpRequest request, EventBuilder event, RealmModel realm, UserModel user, Set<String> ignoredActions) {
|
||||
final var kcAction = authSession.getClientNote(Constants.KC_ACTION);
|
||||
final var firstApplicableRequiredAction =
|
||||
getFirstApplicableRequiredAction(realm, authSession, user, kcAction);
|
||||
getFirstApplicableRequiredAction(realm, authSession, user, kcAction, ignoredActions);
|
||||
|
||||
if (firstApplicableRequiredAction != null) {
|
||||
return executeAction(session, authSession, firstApplicableRequiredAction, request, event, realm, user,
|
||||
|
@ -1265,11 +1265,13 @@ public class AuthenticationManager {
|
|||
if (actionProvider.initiatedActionSupport() == InitiatedActionSupport.NOT_SUPPORTED) {
|
||||
logger.debugv("Requested action {0} does not support being invoked with kc_action", factory.getId());
|
||||
setKcActionStatus(factory.getId(), RequiredActionContext.KcActionStatus.ERROR, authSession);
|
||||
return null;
|
||||
ignoredActions.add(factory.getId());
|
||||
return nextActionAfterAuthentication(session, authSession, session.getContext().getConnection(), request, session.getContext().getUri(), event, ignoredActions);
|
||||
} else if (!model.isEnabled()) {
|
||||
logger.debugv("Requested action {0} is disabled and can't be invoked with kc_action", factory.getId());
|
||||
setKcActionStatus(factory.getId(), RequiredActionContext.KcActionStatus.ERROR, authSession);
|
||||
return null;
|
||||
ignoredActions.add(factory.getId());
|
||||
return nextActionAfterAuthentication(session, authSession, session.getContext().getConnection(), request, session.getContext().getUri(), event, ignoredActions);
|
||||
} else {
|
||||
authSession.setClientNote(Constants.KC_ACTION_EXECUTING, factory.getId());
|
||||
}
|
||||
|
@ -1311,9 +1313,9 @@ public class AuthenticationManager {
|
|||
}
|
||||
|
||||
private static RequiredActionProviderModel getFirstApplicableRequiredAction(final RealmModel realm,
|
||||
final AuthenticationSessionModel authSession, final UserModel user, final String kcAction) {
|
||||
final AuthenticationSessionModel authSession, final UserModel user, final String kcAction, final Set<String> ignoredActions) {
|
||||
final var applicableRequiredActionsSorted =
|
||||
getApplicableRequiredActionsSorted(realm, authSession, user, kcAction);
|
||||
getApplicableRequiredActionsSorted(realm, authSession, user, kcAction, ignoredActions);
|
||||
|
||||
final RequiredActionProviderModel firstApplicableRequiredAction;
|
||||
if (applicableRequiredActionsSorted.isEmpty()) {
|
||||
|
@ -1328,7 +1330,7 @@ public class AuthenticationManager {
|
|||
}
|
||||
|
||||
private static List<RequiredActionProviderModel> getApplicableRequiredActionsSorted(final RealmModel realm,
|
||||
final AuthenticationSessionModel authSession, final UserModel user, final String kcActionAlias) {
|
||||
final AuthenticationSessionModel authSession, final UserModel user, final String kcActionAlias, final Set<String> ignoredActions) {
|
||||
final Set<String> nonInitiatedActionAliases = new HashSet<>();
|
||||
nonInitiatedActionAliases.addAll(user.getRequiredActionsStream().toList());
|
||||
nonInitiatedActionAliases.addAll(authSession.getRequiredActions());
|
||||
|
@ -1336,6 +1338,7 @@ public class AuthenticationManager {
|
|||
final var applicableNonInitiatedActions = nonInitiatedActionAliases.stream()
|
||||
.map(alias -> getApplicableRequiredAction(realm, alias))
|
||||
.filter(Objects::nonNull)
|
||||
.filter(model -> !ignoredActions.contains(model.getProviderId()))
|
||||
.collect(Collectors.toMap(RequiredActionProviderModel::getAlias, Function.identity()));
|
||||
|
||||
RequiredActionProviderModel kcAction = null;
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
*/
|
||||
package org.keycloak.testsuite.actions;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.authentication.requiredactions.TermsAndConditions;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -27,6 +29,8 @@ import org.keycloak.testsuite.AbstractTestRealmKeycloakTest;
|
|||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.VerifyEmailPage;
|
||||
import org.keycloak.testsuite.updaters.UserAttributeUpdater;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -49,6 +53,9 @@ public class AppInitiatedActionTest extends AbstractTestRealmKeycloakTest {
|
|||
@Page
|
||||
protected LoginPage loginPage;
|
||||
|
||||
@Page
|
||||
protected VerifyEmailPage verifyEmailPage;
|
||||
|
||||
@Test
|
||||
public void executeUnknownAction() {
|
||||
oauth.kcAction("nosuch").openLoginForm();
|
||||
|
@ -93,4 +100,32 @@ public class AppInitiatedActionTest extends AbstractTestRealmKeycloakTest {
|
|||
testRealm().flows().updateRequiredAction("CONFIGURE_TOTP", configureTotp);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executeActionWithVerifyEmailUnsupportedAIA() throws IOException {
|
||||
RealmResource realm = testRealm();
|
||||
RequiredActionProviderRepresentation model = realm.flows().getRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL.name());
|
||||
int prevPriority = model.getPriority();
|
||||
|
||||
try (UserAttributeUpdater userUpdater = UserAttributeUpdater
|
||||
.forUserByUsername(realm, "test-user@localhost")
|
||||
.setRequiredActions(UserModel.RequiredAction.VERIFY_EMAIL).update()) {
|
||||
// Set max priority for verify email (AIA not supported) to be executed before update password
|
||||
model.setPriority(1);
|
||||
realm.flows().updateRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL.name(), model);
|
||||
|
||||
oauth.kcAction(UserModel.RequiredAction.UPDATE_PASSWORD.name()).openLoginForm();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
|
||||
// the update password should be displayed
|
||||
passwordUpdatePage.assertCurrent();
|
||||
passwordUpdatePage.changePassword("password", "password");
|
||||
|
||||
// once the AIA password is executed the verify profile should be displayed for the login
|
||||
verifyEmailPage.assertCurrent();
|
||||
} finally {
|
||||
model.setPriority(prevPriority);
|
||||
realm.flows().updateRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL.name(), model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue