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; package org.keycloak.organization.jpa;
import org.keycloak.Config;
import org.keycloak.Config.Scope; import org.keycloak.Config.Scope;
import org.keycloak.models.GroupModel; import org.keycloak.models.GroupModel;
import org.keycloak.models.GroupModel.GroupEvent; import org.keycloak.models.GroupModel.GroupEvent;
@ -88,8 +89,8 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
} }
private void addOrganizationFirstBrokerFlowStep(RealmModel realm) { private void addOrganizationFirstBrokerFlowStep(RealmModel realm) {
AuthenticationFlowModel firstBrokerLoginFlow = realm.getFirstBrokerLoginFlow();
AuthenticationFlowModel firstBrokerLoginFlow = realm.getFirstBrokerLoginFlow();
if (firstBrokerLoginFlow == null) { if (firstBrokerLoginFlow == null) {
return; return;
} }
@ -100,18 +101,44 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
return; return;
} }
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(); AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(firstBrokerLoginFlow.getId()); 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.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setAuthenticator(IdpOrganizationAuthenticatorFactory.ID); execution.setAuthenticator(IdpOrganizationAuthenticatorFactory.ID);
execution.setPriority(50); execution.setPriority(20);
execution.setAuthenticatorFlow(false); execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution); realm.addAuthenticatorExecution(execution);
} }
}
public void addOrganizationBrowserFlowStep(RealmModel realm) { public void addOrganizationBrowserFlowStep(RealmModel realm) {
AuthenticationFlowModel browserFlow = realm.getBrowserFlow();
AuthenticationFlowModel browserFlow = realm.getBrowserFlow();
if (browserFlow == null) { if (browserFlow == null) {
return; return;
} }
@ -122,14 +149,52 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
return; return;
} }
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(); AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(browserFlow.getId()); execution.setParentFlow(browserFlow.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE); execution.setRequirement(AuthenticationExecutionModel.Requirement.ALTERNATIVE);
execution.setAuthenticator(OrganizationAuthenticatorFactory.ID); execution.setFlowId(organizations.getId());
execution.setPriority(26); execution.setPriority(26);
execution.setAuthenticatorFlow(false); execution.setAuthenticatorFlow(true);
realm.addAuthenticatorExecution(execution);
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);
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); realm.addAuthenticatorExecution(execution);
} }
}
} }

View file

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

View file

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