Move organization authenticator into conditional subflows in the default browser and first broker login flows

Closes #29446

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
Stefan Guilhen 2024-05-22 10:54:07 -03:00 committed by Pedro Igor
parent bb1284704d
commit 37f85937a7
4 changed files with 96 additions and 18 deletions

View file

@ -17,6 +17,7 @@
package org.keycloak.organization.jpa;
import org.keycloak.Config;
import org.keycloak.Config.Scope;
import org.keycloak.models.GroupModel;
import org.keycloak.models.GroupModel.GroupEvent;
@ -88,8 +89,8 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
}
private void addOrganizationFirstBrokerFlowStep(RealmModel realm) {
AuthenticationFlowModel firstBrokerLoginFlow = realm.getFirstBrokerLoginFlow();
AuthenticationFlowModel firstBrokerLoginFlow = realm.getFirstBrokerLoginFlow();
if (firstBrokerLoginFlow == null) {
return;
}
@ -100,18 +101,44 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
return;
}
AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(firstBrokerLoginFlow.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setAuthenticator(IdpOrganizationAuthenticatorFactory.ID);
execution.setPriority(50);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
if (!Config.getAdminRealm().equals(realm.getName())) {
// do not add the org flows to the master realm for now.
AuthenticationFlowModel conditionalOrg = new AuthenticationFlowModel();
conditionalOrg.setTopLevel(false);
conditionalOrg.setBuiltIn(true);
conditionalOrg.setAlias("First Broker Login - Conditional Organization");
conditionalOrg.setDescription("Flow to determine if the authenticator that adds organization members is to be used");
conditionalOrg.setProviderId("basic-flow");
conditionalOrg = realm.addAuthenticationFlow(conditionalOrg);
AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(firstBrokerLoginFlow.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.CONDITIONAL);
execution.setFlowId(conditionalOrg.getId());
execution.setPriority(50);
execution.setAuthenticatorFlow(true);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOrg.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setAuthenticator("conditional-user-configured");
execution.setPriority(10);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOrg.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setAuthenticator(IdpOrganizationAuthenticatorFactory.ID);
execution.setPriority(20);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
}
public void addOrganizationBrowserFlowStep(RealmModel realm) {
AuthenticationFlowModel browserFlow = realm.getBrowserFlow();
AuthenticationFlowModel browserFlow = realm.getBrowserFlow();
if (browserFlow == null) {
return;
}
@ -122,14 +149,52 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
return;
}
AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
if (!Config.getAdminRealm().equals(realm.getName())) {
// do not add the org flows to the master realm for now.
AuthenticationFlowModel organizations = new AuthenticationFlowModel();
organizations.setTopLevel(false);
organizations.setBuiltIn(true);
organizations.setAlias("Organization");
organizations.setProviderId("basic-flow");
organizations = realm.addAuthenticationFlow(organizations);
AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(browserFlow.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
execution.setFlowId(organizations.getId());
execution.setPriority(26);
execution.setAuthenticatorFlow(true);
realm.addAuthenticatorExecution(execution);
execution.setParentFlow(browserFlow.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
execution.setAuthenticator(OrganizationAuthenticatorFactory.ID);
execution.setPriority(26);
execution.setAuthenticatorFlow(false);
AuthenticationFlowModel conditionalOrg = new AuthenticationFlowModel();
conditionalOrg.setTopLevel(false);
conditionalOrg.setBuiltIn(true);
conditionalOrg.setAlias("Browser - Conditional Organization");
conditionalOrg.setDescription("Flow to determine if the organization identity-first login is to be used");
conditionalOrg.setProviderId("basic-flow");
conditionalOrg = realm.addAuthenticationFlow(conditionalOrg);
execution = new AuthenticationExecutionModel();
execution.setParentFlow(organizations.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.CONDITIONAL);
execution.setFlowId(conditionalOrg.getId());
execution.setPriority(10);
execution.setAuthenticatorFlow(true);
realm.addAuthenticatorExecution(execution);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOrg.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setAuthenticator("conditional-user-configured");
execution.setPriority(10);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
execution = new AuthenticationExecutionModel();
execution.setParentFlow(conditionalOrg.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
execution.setAuthenticator(OrganizationAuthenticatorFactory.ID);
execution.setPriority(20);
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
}
}
}

View file

@ -77,7 +77,7 @@ public class IdpOrganizationAuthenticatorFactory implements AuthenticatorFactory
@Override
public String getDisplayType() {
return "Organization";
return "Organization Member Onboard";
}
@Override

View file

@ -190,4 +190,9 @@ public class OrganizationAuthenticator extends IdentityProviderAuthenticator {
return email.substring(domainSeparator + 1);
}
@Override
public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) {
return realm.isOrganizationsEnabled();
}
}

View file

@ -17,6 +17,8 @@
package org.keycloak.organization.authentication.authenticators.browser;
import java.util.List;
import org.keycloak.Config.Scope;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticatorFactory;
@ -24,6 +26,7 @@ import org.keycloak.common.Profile;
import org.keycloak.common.Profile.Feature;
import org.keycloak.models.KeycloakSession;
import org.keycloak.provider.EnvironmentDependentProviderFactory;
import org.keycloak.provider.ProviderConfigProperty;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -39,7 +42,7 @@ public class OrganizationAuthenticatorFactory extends IdentityProviderAuthentica
@Override
public String getDisplayType() {
return "Organization Identity Provider Redirector";
return "Organization Identity-First Login";
}
@Override
@ -56,4 +59,9 @@ public class OrganizationAuthenticatorFactory extends IdentityProviderAuthentica
public boolean isSupported(Scope config) {
return Profile.isFeatureEnabled(Feature.ORGANIZATION);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() { // org identity-first login
return List.of();
}
}