Skip to content

Commit

Permalink
Merge pull request #980 from f11h/fix/auth-flow-with-multiple-executi…
Browse files Browse the repository at this point in the history
…ons-of-same-type

Fix: Multiple Usage of Authenticators/Conditions in Authentication Sub-Flows
  • Loading branch information
francis-pouatcha authored Oct 17, 2024
2 parents 565d101 + df6c14d commit 46d83c1
Show file tree
Hide file tree
Showing 4 changed files with 450 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Fixed

- Allow executions of same provider with different configurations in Sub-Auth-Flows
- Fix enabling a realm clears the value of eventsExpiration

## [6.1.11] - 2024-10-14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public List<AuthenticationExecutionInfoRepresentation> getExecutionFlowsByAlias(
String topLevelFlowAlias,
AuthenticationExecutionExportRepresentation execution) {
List<AuthenticationExecutionInfoRepresentation> executions = searchByAlias(
realmName, topLevelFlowAlias, execution.getAuthenticator(), execution.getFlowAlias());
realmName, topLevelFlowAlias, execution.getAuthenticator(),
execution.getFlowAlias(), execution.getAuthenticatorConfig());

if (executions.isEmpty()) {
String withSubFlow = execution.getFlowAlias() != null
Expand Down Expand Up @@ -147,11 +148,18 @@ private List<AuthenticationExecutionInfoRepresentation> searchByAlias(
String realmName,
String topLevelFlowAlias,
String executionProviderId,
String subFlowAlias
String subFlowAlias,
String authenticationConfig
) {
return getExecutionsByAuthFlow(realmName, topLevelFlowAlias)
.stream()
.filter(f -> Objects.equals(f.getProviderId(), executionProviderId))
.filter(f -> {
if (authenticationConfig != null && f.getAlias() != null) {
return Objects.equals(f.getAlias(), authenticationConfig);
}
return true;
})
.filter(f -> {
if (subFlowAlias != null) {
return Objects.equals(f.getDisplayName(), subFlowAlias);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static de.adorsys.keycloak.config.test.util.KeycloakRepository.getAuthenticatorConfig;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -798,6 +799,62 @@ void shouldUpdateMultipleExecutionsWithSameAuthenticatorWithConfig() throws IOEx
assertThat(authConfig.get(0).getConfig(), hasEntry(is("defaultProvider"), is("id4")));
}

@Test
@Order(33)
void shouldCreateMultipleSubFlowExecutionsWithSameAuthenticator() throws IOException {
doImport("33_update_realm__add_multiple_subflow_executions_with_same_authenticator.json");

RealmRepresentation realm = keycloakProvider.getInstance().realm(REALM_NAME).partialExport(true, true);

AuthenticationFlowRepresentation topLevelFlow = getAuthenticationFlow(realm, "my top level auth flow");
assertThat(topLevelFlow.isBuiltIn(), is(false));
assertThat(topLevelFlow.isTopLevel(), is(true));
assertThat(topLevelFlow.getAuthenticationExecutions().size(), is(1));
assertThat(topLevelFlow.getAuthenticationExecutions().get(0).getFlowAlias(), is("my sub auth flow"));

AuthenticationFlowRepresentation subFlow = getAuthenticationFlow(realm, "my sub auth flow");
assertThat(subFlow.isBuiltIn(), is(false));
assertThat(subFlow.isTopLevel(), is(false));
assertThat(subFlow.getAuthenticationExecutions().size(), is(3));

List<AuthenticationExecutionExportRepresentation> execution;
execution = getExecutionFromFlow(subFlow, "identity-provider-redirector");
assertThat(execution, hasSize(2));

List<AuthenticationExecutionExportRepresentation> executionsId1 = execution.stream()
.filter((config) -> config.getAuthenticatorConfig() != null)
.filter((config) -> config.getAuthenticatorConfig().equals("config-1"))
.collect(Collectors.toList());

assertThat(executionsId1, hasSize(1));
assertThat(executionsId1.get(0).getAuthenticator(), is("identity-provider-redirector"));
assertThat(executionsId1.get(0).getAuthenticatorConfig(), is("config-1"));
assertThat(executionsId1.get(0).getRequirement(), is("ALTERNATIVE"));

List<AuthenticationExecutionExportRepresentation> executionsId2 = execution.stream()
.filter((config) -> config.getAuthenticatorConfig() != null)
.filter((config) -> config.getAuthenticatorConfig().equals("config-2"))
.collect(Collectors.toList());

assertThat(executionsId2, hasSize(1));
assertThat(executionsId2.get(0).getAuthenticator(), is("identity-provider-redirector"));
assertThat(executionsId2.get(0).getAuthenticatorConfig(), is("config-2"));
assertThat(executionsId2.get(0).getRequirement(), is("ALTERNATIVE"));

assertThat(executionsId2.get(0).getPriority(), greaterThan(executionsId1.get(0).getPriority()));

List<AuthenticatorConfigRepresentation> authConfig;
authConfig = getAuthenticatorConfig(realm, "config-1");
assertThat(authConfig, hasSize(1));
assertThat(authConfig.get(0).getAlias(), is("config-1"));
assertThat(authConfig.get(0).getConfig(), hasEntry(is("defaultProvider"), is("id1")));

authConfig = getAuthenticatorConfig(realm, "config-2");
assertThat(authConfig, hasSize(1));
assertThat(authConfig.get(0).getAlias(), is("config-2"));
assertThat(authConfig.get(0).getConfig(), hasEntry(is("defaultProvider"), is("id2")));
}

@Test
@Order(40)
void shouldFailWhenTryingToUpdateBuiltInFlow() throws IOException {
Expand Down
Loading

0 comments on commit 46d83c1

Please sign in to comment.