Do not add steps if feature disabled in default flows

Allow login if a step is disabled even the authenticator is not enabled by profile
Closes #40954

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2025-07-07 09:50:28 +02:00 committed by Marek Posolda
parent 966aab5585
commit d62114e50e
3 changed files with 51 additions and 29 deletions

View File

@ -387,22 +387,26 @@ public class DefaultAuthenticationFlows {
realm.addAuthenticatorExecution(execution);
// webauthn as disabled
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("webauthn-authenticator");
execution.setPriority(30);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
if (Profile.isFeatureEnabled(Profile.Feature.WEB_AUTHN)) {
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("webauthn-authenticator");
execution.setPriority(30);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
// recovery-codes as disabled
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("auth-recovery-authn-code-form");
execution.setPriority(40);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
if (Profile.isFeatureEnabled(Profile.Feature.RECOVERY_CODES)) {
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("auth-recovery-authn-code-form");
execution.setPriority(40);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
addOrganizationBrowserFlowStep(realm, browser);
}
@ -669,22 +673,26 @@ public class DefaultAuthenticationFlows {
realm.addAuthenticatorExecution(execution);
// webauthn as disabled
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("webauthn-authenticator");
execution.setPriority(30);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
if (Profile.isFeatureEnabled(Profile.Feature.WEB_AUTHN)) {
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("webauthn-authenticator");
execution.setPriority(30);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
// recovery-codes as disabled
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("auth-recovery-authn-code-form");
execution.setPriority(40);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
if (Profile.isFeatureEnabled(Profile.Feature.RECOVERY_CODES)) {
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOTP.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
execution.setAuthenticator("auth-recovery-authn-code-form");
execution.setPriority(40);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
addOrganizationFirstBrokerFlowStep(realm, firstBrokerLogin);
}

View File

@ -357,7 +357,8 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
}
private boolean isConditionalAuthenticator(AuthenticationExecutionModel model) {
return !model.isAuthenticatorFlow() && model.getAuthenticator() != null && createAuthenticator(getAuthenticatorFactory(model)) instanceof ConditionalAuthenticator;
return !model.isAuthenticatorFlow() && model.getAuthenticator() != null && model.isEnabled()
&& createAuthenticator(getAuthenticatorFactory(model)) instanceof ConditionalAuthenticator;
}
private AuthenticatorFactory getAuthenticatorFactory(AuthenticationExecutionModel model) {

View File

@ -1005,6 +1005,19 @@ public class LoginTest extends AbstractChangeImportedUserPasswordsTest {
events.expectLogin().user(userId).assertEvent();
}
@Test
public void loginSuccessfulWithoutWebAuthn() {
testingClient.disableFeature(Profile.Feature.WEB_AUTHN);
try {
loginPage.open();
loginPage.login("test-user@localhost", getPassword("test-user@localhost"));
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
events.expectLogin().assertEvent();
} finally {
testingClient.enableFeature(Profile.Feature.WEB_AUTHN);
}
}
@Test
public void testExecuteActionIfSessionExists() {
loginPage.open();